OIIA CAT - ACCESSORY EXAMPLES

Two cats, basically.
Oiia Cat is one accessory you can place on your dress.
Oiia Cat Parade is a trim. Draw its path and the cats repeat along it.
Both are unlocked from the start.

INSTALL

Needs Dressmaker Mod Loader v0.6.37 or newer.
Install this ZIP from Mod Manager, or put the oiia-cat folder inside Dressmaker/Mods.
Restart Dressmaker. Look for Oiia Cat and Oiia Cat Parade in the accessory shop.
Buy the trim and place it using the usual trim controls. Its pins still work normally.

WHAT IS IN HERE

mod.json - the pack and its two accessory definitions.
cat-texture.png - the original 4096 x 4096 texture, shared by both cats.
icon.png - the shop and pack thumbnail.
cat-single.mesh.json - the larger, detailed cat. 15,774 triangles, about 6 cm tall.
cat-trim.mesh.json - the smaller cat for repeating. 3,494 triangles, about 3 cm tall.

The supplied FBX was converted to static meshes. The animation and skeleton are not included.
The original FBX and texture came from the supplied oiiaioooooiai-cat folder.
Yuuma is the example pack author; this does not credit Yuuma as the original cat model artist.

MAKE YOUR OWN VERSION

Copy this folder. Change the pack id, name, author, and version in mod.json.
Give each accessory its own id and name. New ids make new items; keeping an id updates that item.
Keep ids stable after sharing a pack, so saved dresses can still find the same items.
Use letters, numbers, dots, underscores, or hyphens for ids.

Recolor cat-texture.png and save it with the same layout. Do not move the texture islands.
Update icon.png too if you want the shop thumbnail to match.
Both cats use the same texture. To give them different colors, copy the PNG and change
one accessory's texture field to the new filename.

Only want one of the cats? Remove the other object from the accessories array.
To share it, ZIP your pack folder with mod.json and its files inside.
No DLL compiling needed for packs. The loader creates the game objects for you.

PACK FIELDS

id - the unique pack id. Example: yourname.cat-pack.
name - the pack name shown in Mod Manager.
author - your name.
version - the pack version. Increase it when you update the pack.
icon - the pack thumbnail filename.
accessories - a list of items. You can add several in one pack.

ACCESSORY FIELDS

id - unique within this pack. The game uses pack id + accessory id to identify it.
name - the item name in the shop.
baseAccessory - the existing item whose placement behavior and shader are copied.
  Applique Luna Moth gives this cat single-item placement.
  Trim Pearl Beads gives the parade native trim placement.
accessoryType - the shop category. Here it is Other or Trim.
model - the JSON mesh file. A custom trim repeats this model along its path.
texture - the image used on the model. PNG keeps transparency; JPEG also works.
icon - the item thumbnail image.
cost - item price, using the base accessory's usual purchasing behavior.
unlockLevel - the prestige level needed, from 0 to 50. Zero makes it available immediately.
tagWeights - styles the item contributes to your dress. Each entry has tag and weight.
  Use names from ReferencesForModding/accessory-reference.json, such as Cute or Playful.
notes - optional item notes.
beadSpacing - for a custom trim only, distance between repeats in metres at default width.
  0.04 is 4 cm. Bigger numbers leave more room; smaller numbers make more cats.
  Allowed: 0.005 through 1. The game's trim width control also scales the spacing.
  Leave it out to use the base trim's spacing. The game samples the path, so spacing is approximate.

OTHER OPTIONS

reuseAsset: true copies the original model instead of loading your own.
Leave it out for these custom cats. It is useful for recoloring existing accessories,
like the Luna Moth template or Golden Scale Mail Chain.

material is an optional object for shader settings. Custom models keep the base shader.
The loader starts custom models with a matte material, to avoid very bright reflections.
For example, add this inside an accessory object to give it some shine:

  "material": {
    "floats": {
      "_Smoothness": 0.2,
      "_SpecularLightStrength": 0.15
    }
  }

The material supports color, floats, ints, colors, vectors, textures, textureScales,
textureOffsets, keywords, and renderQueue. Only use properties supported by that shader.
For these custom models, texture remains the main color image; material.textures can
supply other maps. Shader changes are not supported for accessories.

SIZE AND ORIENTATION

Mesh positions are in metres. X is left/right, Y is up, and +Z faces out from the garment.
These cats have their nearest surface at Z=0, so their bodies project out from the dress.
For a trim, Y follows the path and +Z follows the surface normal.
The mesh files contain positions, uvs, and triangles. UVs tell the texture where to go.
Do not edit these arrays by hand unless you know what you want to change.

To resize a cat, multiply its positions by a scale, such as 0.5 to halve it.
Do not scale the UVs or triangle indices. You can also use the game's placement controls.
If you resize the trim mesh, adjust beadSpacing to leave enough room between cats.

LIMITS

Models use the loader's JSON mesh format, up to 65,535 vertices and 8 MB per model.
FBX is not loaded directly in-game. Convert it first, preserving UVs and triangle winding.
A single accessory needs a single-item base; a repeating trim needs a trim-path base.
Keep trim meshes light. A row of 30 cats means the game renders that mesh 30 times.
This is a static accessory example, not a garment, animated pet, or sewing pattern.

FROM A 3D MODEL TO A DRESSMAKER ACCESSORY

The game does not read OBJ or FBX directly through this loader.
The model needs to become a .mesh.json file. Your texture stays a separate PNG or JPEG.
You can do the conversion in Blender. No browser tool or DLL compiling needed.

1. IMPORT YOUR MODEL

Open Blender and remove the default cube.
Use File > Import > Wavefront (.obj), FBX (.fbx), or glTF 2.0 (.glb/.gltf).
For other formats, use Blender's matching importer or export an OBJ from the original app.
Not every format has a built-in importer. Renaming the extension will not convert it.

For this cat, import source/OiiaioooooiaiFin.fbx from the original download.
The texture is textures/Muchkin2_BaseColor.png.

2. CHECK THE TEXTURE

The model needs a UV map. This tells the texture which parts of the model to color.
In Blender's Shading workspace, check that your image is connected to the material's Base Color.
Use Material Preview to check it. If it looks wrong, fix the UVs or texture before exporting.
The loader uses one color texture for the whole accessory. Models with several different
textures need those textures combined into one atlas, with the UVs updated to match.

Copy your color image into the mod folder. Blender materials are not exported by this script.
The example uses cat-texture.png. An image packed inside an FBX/GLB needs to be saved out separately.

3. PREPARE THE MODEL

Select only the mesh objects you want in the accessory. Do not select the mannequin or background.
Several selected mesh objects are combined into one accessory mesh.

In Blender, Z is up. Have the accessory's front face toward -Y.
That becomes up and out from the garment in Dressmaker.
Rotate the model if necessary. The script includes object transforms and evaluated modifiers,
so you do not have to apply those transforms just for this export.

For an animated model, choose the pose you want first. This exports that pose as a static mesh.
The skeleton and animation do not become an animated accessory.

For a repeating trim, duplicate the model in Blender and simplify the duplicate first.
A Decimate modifier can reduce its triangles. Check the face, paws, and texture afterward.
A long trim repeats the same model many times, so keep it lighter than a single accessory.
The example uses 15,774 triangles for the single cat and 3,494 for the trim cat.

4. EXPORT THE MESH JSON

Switch to Blender's Scripting workspace. In the Text Editor, click New.
Paste the script below. Change OUTPUT to a real file path on your computer.
Change HEIGHT_CM to the height you want: 6 for the single cat, or 3 for the trim.
The export is centered and placed just outside the garment.
Run the script with the Text Editor's Run Script button.

--- COPY FROM HERE ---

import bpy
import json
from pathlib import Path

OUTPUT = Path(r"C:\Users\YourName\Downloads\cat-single.mesh.json")
HEIGHT_CM = 6.0

if not 0 < HEIGHT_CM <= 100:
    raise ValueError("Choose a height above 0 and at most 100 cm.")
objects = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']
if not objects:
    raise ValueError("Select your accessory mesh first.")

positions, uvs, triangles = [], [], []
graph = bpy.context.evaluated_depsgraph_get()
for obj in objects:
    evaluated = obj.evaluated_get(graph)
    mesh = evaluated.to_mesh()
    try:
        if not mesh.uv_layers.active:
            raise ValueError(obj.name + " needs a UV map.")
        mesh.calc_loop_triangles()
        lookup = {}
        mirrored_object = evaluated.matrix_world.determinant() < 0
        for triangle in mesh.loop_triangles:
            corners = []
            for loop_index in triangle.loops:
                vertex_index = mesh.loops[loop_index].vertex_index
                uv = mesh.uv_layers.active.data[loop_index].uv
                point = evaluated.matrix_world @ mesh.vertices[vertex_index].co
                position = (-point.x, point.z, -point.y)
                key = (vertex_index, float(uv.x), float(uv.y))
                if key not in lookup:
                    lookup[key] = len(positions)
                    positions.append(position)
                    uvs.append((float(uv.x), float(uv.y)))
                corners.append(lookup[key])
            triangles.extend(corners if mirrored_object else corners[::-1])
    finally:
        evaluated.to_mesh_clear()

if not positions or not triangles:
    raise ValueError("The selected meshes have no triangles.")
low = [min(point[axis] for point in positions) for axis in range(3)]
high = [max(point[axis] for point in positions) for axis in range(3)]
height = high[1] - low[1]
if height <= 0:
    raise ValueError("The model needs some height. Check its orientation.")
scale = HEIGHT_CM / 100.0 / height
origin = ((low[0] + high[0]) / 2, (low[1] + high[1]) / 2, low[2])
result = {
    "positions": [round((point[axis] - origin[axis]) * scale, 7)
                  for point in positions for axis in range(3)],
    "uvs": [value for pair in uvs for value in pair],
    "triangles": triangles
}
if len(positions) > 65535 or len(triangles) > 393210:
    raise ValueError("Too much geometry for the loader. Simplify the model first.")
content = json.dumps(result, separators=(',', ':'), allow_nan=False)
if len(content.encode('utf-8')) > 8 * 1024 * 1024:
    raise ValueError("Mesh JSON is over 8 MB. Simplify the model first.")
OUTPUT.write_text(content, encoding='utf-8')
print("Exported:", OUTPUT, "Vertices:", len(positions), "Triangles:", len(triangles) // 3)

--- END OF SCRIPT ---

Export the detailed model as cat-single.mesh.json with HEIGHT_CM = 6.
Then select your simplified version, change OUTPUT to cat-trim.mesh.json,
change HEIGHT_CM to 3, and run it again.

5. REGISTER IT IN THE PACK

Copy the exported JSON files into your mod folder. In mod.json:

  "model": "cat-single.mesh.json",
  "texture": "cat-texture.png",
  "icon": "icon.png"

For a single accessory, use a single-item base such as Applique Luna Moth.
For a repeating trim, use a trim base such as Trim Pearl Beads, point model at
cat-trim.mesh.json, and set beadSpacing. The example uses 0.04 metres, or 4 cm.

Change the pack and accessory ids and names for your own mod.
Restart Dressmaker and try it on a dress. Check the orientation, size, texture, and trim spacing.
If something needs changing, adjust the model in Blender and export again.
Keep the same ids when updating an existing item.

If the export fails, check Blender's error message. Common causes are no selected mesh,
no UV map, a wrong output path, or too much geometry. The destination folder must already exist.
This exports the model data only; the game handles its normals, shader, and placement behavior.
