Mod Loader/Reference/Accessory placement API
AccessoryPlacementApi lets a C# plugin measure or snap an individual accessory while the player places it on a dress. It works with buttons, bows, and other single items. Pass includeTrims: true when registering to use the same rule for trim points. Trim support and the surface grid require Mod Loader 0.6.80.
Register a placement rule
Call AccessoryPlacementApi.Register(id, callback) from Awake and dispose its handle when your plugin unloads. The callback runs on the Unity main thread while the player previews or places a single accessory. Return null when your rule has nothing to do. If several rules are registered, the first one returning a suggestion controls that frame.
The context has Position, LastPosition, and PreviousPosition as mannequin-local X/Y coordinates in metres. X is sideways; Y is up the garment. Check HasLast and HasPrevious before using those positions. The last two items follow the dress's accessory placement order, including items restored from a save. For single accessories, trim paths are skipped when finding the last item.
This complete plugin keeps each new accessory on the same vertical line as the last one. It is always active after the first accessory is placed. For an optional hold-to-snap action, register a key with the Keybind API and return null while that key is not held.
using System;
using BepInEx;
using DressmakerMods;
using UnityEngine;
[BepInPlugin("example.placement", "Vertical Placement", "1.0.0")]
[BepInDependency("yuu.dressmaker.mods", "0.6.79")]
public sealed class VerticalPlacement : BaseUnityPlugin
{
private IDisposable placementRule;
private void Awake()
{
placementRule = AccessoryPlacementApi.Register("example.placement", context =>
{
if (!context.HasLast) return null;
return new AccessoryPlacementSuggestion {
ShowMeasurement = true,
Snap = true,
Target = new Vector2(context.LastPosition.x, context.Position.y),
GuideAxis = AccessoryGuideAxis.Vertical
};
});
}
private void OnDestroy() => placementRule?.Dispose();
}
Trim points
Use AccessoryPlacementApi.Register(id, callback, includeTrims: true) to receive trim previews and placements too. Check context.IsTrimPoint if your rule needs different behaviour for trims.
When extending a trim, LastPosition is its end point and PreviousPosition is the next point inward. When moving a point, they are the preceding points; moving the first point uses the following points instead. The first point of a new trim has no history. Check HasLast before applying a line lock.
To show a local grid on the dress, set GridSpacing on your suggestion to its spacing in metres (for example, 0.005f for 0.5 cm). Zero hides it. The grid is anchored to LastPosition, or the mannequin origin when there is no last point. Set Snap and Target separately to place on that grid.
A plugin that inserts its own trim points can call TryResolveTrimPoint(controller, path, insertionIndex, ref point, ref normal) before inserting. Supply world coordinates. The method changes them to the requested snap position and returns false if it cannot find a surface there. The caller must still check the completed path and available trim length.
Placement context
| Property | Meaning |
|---|---|
IsTrimPoint
|
True when editing a point on a trim. Only supplied to rules that opt in. |
Position
|
Current preview position in the mannequin's X/Y plane, in metres. |
LastPosition, HasLast
|
Position of the last single accessory. Check HasLast before using it. |
PreviousPosition, HasPrevious
|
Position of the accessory before that. Use both positions to calculate an equal gap. |
Placement suggestion
| Property | Effect |
|---|---|
Snap, Target
|
When Snap is true, projects Target onto a visible dress panel. If no panel is found there, clicking does not place the item. |
ShowMeasurement
|
Draws a bracket and distance from the last accessory. |
DetailedMeasurement
|
Adds separate sideways and up/down distances. |
GuideAxis
|
Selects a horizontal or vertical yellow guide line. |
GridSpacing
|
Surface grid spacing in metres; zero hides it. |
ModeLabel
|
Adds a short label beside the measurement. |
Distances are measured in the mannequin's X/Y plane. They do not follow the curve of the fabric.
Use the Keybind API if the player should be able to hold a remappable key to turn a placement rule on. The accessory guide covers making the accessory itself.