Mod Loader/Reference/Fabric API
FabricModApi registers fabrics from a BepInEx plugin. For a fabric you can make in the game or describe with mod.json, see Make a fabric.
This example adds a copy of Cotton Black with a different name and price. It uses the game's existing material and texture.
Set up a plugin
Reference DressmakerMods.dll, Assembly-CSharp.dll, and UnityEngine.CoreModule.dll from the game installation. Add a BepInEx dependency on yuu.dressmaker.mods. Fabric registration needs Mod Loader 0.6.73 or newer; custom types and tags need 0.6.77 or newer.
Call the API on Unity's main thread. Register fabrics inside FabricModApi.WhenReady, after the loader has read content packs. The callback runs immediately if fabrics are already ready.
using BepInEx;
using DressmakerMods;
[BepInPlugin("example.fabrics", "Example Fabrics", "1.0.0")]
[BepInDependency("yuu.dressmaker.mods", "0.6.73")]
public sealed class ExampleFabrics : BaseUnityPlugin
{
private void Start()
{
FabricModApi.WhenReady(() =>
FabricModApi.RegisterFromBase(
Fabric.CottonBlack.name,
"example.fabrics", "shop-cotton", "Shop Cotton",
Paths.PluginPath,
definition => definition.Cost = 15));
}
}
RegisterFromBase copies the base fabric's type, colors, tags, texture, material, price, unlock level, and notes for fields you leave unset. The example names its copy Shop Cotton and sets the price to 15. Keep the mod ID and local ID when you update: saved inventories and dresses can refer to example.fabrics.shop-cotton.
Methods
| Member | Use |
|---|---|
bool IsReadyvoid WhenReady(Action callback)
|
Wait for manifest fabrics to load. Registration methods require this state. |
Fabric Register(string modId, FabricDefinition definition, string assetDirectory)
|
Register a fabric without copying a base. |
Fabric RegisterFromBase(string baseFabricId, string modId, string localId, string displayName, string assetDirectory, Action<FabricDefinition> configure = null)
|
Copy a native or modded fabric and change selected fields. |
Fabric FindFabric(string id)Fabric[] GetFabrics()
|
Find by full ID, or get a copy of the current fabric list. An unknown ID returns null. |
FabricType RegisterType(string modId, string localId, string displayName)ItemTag RegisterTag(string modId, string localId, string displayName)
|
Make a type or tag with the full ID modId.localId. Call before registering fabrics that use it.
|
FabricType FindType(string id)ItemTag FindTag(string id)
|
Find native or custom types and tags by full ID. |
FabricShaderBundle LoadShaderBundle(string bundlePath, string shaderAssetName)
|
Load a shader from an AssetBundle. The handle has a Shader property and Dispose().
|
FabricDefinition
For Register, set Id, Name, FabricType, Colors, TagWeights, Cost, and UnlockLevel. Supply an image with Texture or RuntimeTexture, and a shader with Material.Shader or RuntimeShader. Material also accepts color, numbers, keywords, texture maps, scales, offsets, and render queue. The file-backed fields are listed in Fabric pack fields.
RuntimeTexture, RuntimeShader, and ConfigureMaterial are C# properties; they are ignored in JSON. ConfigureMaterial receives a new material, so it does not change the base fabric. Use Unity's SetFloat, SetColor, SetVector, SetTexture, keywords, or renderQueue for properties supported by the chosen shader.
Custom types and tags
Register these inside WhenReady before registering a fabric that uses them. Keep the IDs when you update a published mod.
using System.Collections.Generic;
FabricModApi.WhenReady(() =>
{
FabricType leather = FabricModApi.RegisterType("example.leathers", "Leather", "Leather");
ItemTag leatherTag = FabricModApi.RegisterTag("example.leathers", "Leather", "Leather");
FabricModApi.RegisterFromBase(Fabric.CottonBlack.name,
"example.leathers", "brown-leather", "Brown Leather", assetFolder,
definition =>
{
definition.FabricType = leather.name;
definition.TagWeights = new List<FabricTagDefinition> {
new FabricTagDefinition { Tag = leatherTag.name, Weight = 50f }
};
});
});
To make a shader and load it from a plugin, follow Add a custom fabric shader.
Shader bundles
Build a shader AssetBundle for Dressmaker's Unity version and the player's platform, then put it beside your plugin. Add a reference to UnityEngine.AssetBundleModule.dll for bundle loading. LoadShaderBundle checks that the named shader exists and is supported by the current graphics device. Keep the handle until your plugin unloads, then dispose it.
private FabricShaderBundle shaderBundle;
private void Start()
{
string assetFolder = System.IO.Path.Combine(Paths.PluginPath, "ExampleSheerFabric");
string bundlePath = System.IO.Path.Combine(assetFolder, "fabric-shaders");
shaderBundle = FabricModApi.LoadShaderBundle(
bundlePath, "Assets/Shaders/SheerFabric.shader");
FabricModApi.WhenReady(() =>
FabricModApi.RegisterFromBase(Fabric.CottonBlack.name,
"example.sheer", "sheer-cotton", "Sheer Cotton", assetFolder,
definition => definition.RuntimeShader = shaderBundle.Shader));
}
private void OnDestroy() { shaderBundle?.Dispose(); }
The plugin owns its RuntimeTexture and RuntimeShader. Keep them alive while registered fabrics use them. A registered fabric stays until Dressmaker exits; there is no runtime unregister method. A failed registration is discarded so you can correct it and retry.
Keep a pack texture loaded
For custom previews, renderer tracking, and UI images, see the texture use API.
A large fabric image loaded from mod.json may be a small preview until it is displayed. Its Texture2D object stays the same, but its dimensions and pixel data can change. This also applies to custom accessory surface images. Textures supplied through RuntimeTexture or loaded by a C# registration keep their usual ownership.
Use ModTextureApi.Pin before reading pixels or using a pack image in a view the loader does not know about. It loads the original image immediately, so the first call may pause briefly. Keep the returned handle for as long as your view needs the texture, then dispose it.
Fabric fabric = FabricModApi.FindFabric("example.fabrics.blue-linen");
using (System.IDisposable pin = ModTextureApi.Pin(fabric.texture))
{
// The original image is loaded here, even if it was only a preview before.
UnityEngine.Color sample = fabric.texture.GetPixel(0, 0);
}
Call these methods on Unity's main thread. Treat shared pack images as read-only: changes affect other users of that fabric, and eviction discards those changes. Make your own copy if you need to edit pixels. Do not destroy a shared texture.
| Member | Use |
|---|---|
bool IsManaged(Texture texture)
|
Check whether the loader manages this image's resolution. |
IDisposable Pin(Texture texture)
|
Load the original and prevent eviction until the handle is disposed. Multiple callers may hold pins. For a native or plugin-owned image, the handle does nothing and ownership stays unchanged. A managed image that cannot be read throws an exception. |
long ResidentBytes
|
Estimated GPU bytes for managed images and their mipmaps. CPU copies and temporary loads are additional. |
long BudgetBytes
|
The configured soft GPU budget. Images currently in use may exceed it. |
Icons, portraits, art replacements, and extra shader maps are not streamed. Newly imported content uses full-size images until restart. No change to mod.json is needed.
Where a shader appears
The shop bolt and preview use Fabric.material directly. Cutting, mannequin, and finished-garment views often copy matching properties onto a garment material with its own shader. Test cutting, sewing, mannequin, and saved-dress reloads. Use FabricRenderApi to configure those view materials after the game sets them up.