CCXL: Hairs

Summary

Published: Jan 20 2025 by manavortex and IslandDancer Last documented edit: Feb 16 2025 by manavortex, IslandDancer, CyberVesna , nutboy, and Silverlags

This page will tell you how to use ArchiveXL to add hair to the character creator.

Wait, this is not what I want!

Requirements

You have downloaded the example project from Nexus

TL;DR

If you would rather understand what you're doing, please skip to Step 1: Deleting .ent files!

  1. Download example project

  2. Add your .mesh file to the project

  3. Copy the appearances, materialEntries, and localMaterialDefinitions from the template mesh

  4. Overwrite it with your own

  5. Overwrite the .rig and the .animgraph with your own, if you have them

  6. Adjust .app file entry

  7. If you're not using base game textures: Change files paths in the .mi

  8. Rename the .xl file

  9. Change translation key in the .json file to something unique for your mod

  10. Change translation entries in the .inkcharactercustomization file

  11. Custompath everything — do not publish anything that still contains tutorial files!

  12. Profit

Let's go!

We will be moving backwards through the files: starting at the bottom, and working our way to the top (the character creation and the .xl control file).

  1. Start by downloading the example project from Nexus

  2. Unpack the source folder into the root of your existing hair project so that it merges with yours

  3. Move any .mesh, .animgraph, and .rig files from your original hair to your_modder_name\ccxl\your_first_addition\meshes

Step 0: Deleting empty meshes

Starting with 8.16.2, Wolvenkit has the menu option Project -> Clean up -> Delete empty meshes. This will delete placeholder files from your hair mod.

Step 1: Deleting .ent files

If you don't have any .ent files, you're good!

If you do have them, delete them now – we don't need them in our CCXL projects.

Step 2: Adjusting the .app file

If you are converting an existing mod with an .app file

It is often easier to convert the existing file and replace the template mod's .app with it, especially when you are using more than one hair mesh.

  1. Delete all but the first appearance.

  1. partsValues are unused and should be left blank.

  2. partsOverrides are not used by hairstyles in the basegame, but ArchiveXL does use them to generate/expand appearances in .app and to unambiguously resolve meshAppearance per component per appearanceAppearanceDefinition.

  3. ArchiveXL has fallback behavior in the event partsOverrides are missing. It will try to recognize which components are meshes that require meshAppearance to be set, but it it can make incorrect assumptions in complex cases involving many components. Best practice is therefore to add componentOverrides and set componentName and meshAppearance but leave depotPaths blank.

Your .app should look like this:

Your .app partsOverrides should look like this:

Wait, I'm missing meshes!

If you have more than one .mesh file, for every additional mesh, complete the following steps:

  1. Duplicate the entAnimatedComponent

    1. Change the rig 's depot path to the relative path of the corresponding .rig file

    2. Change the graph's depot path to relative path of the corresponding .animgraph file

    3. Change the name so that it's unique (add _pt_1 at the end or number it)

  2. Duplicate the entSkinnedMeshComponent

    1. change the depot path to point it at your extra mesh

    2. Select parentTransform and change the bindName to your entAnimatedComponent's name (step 1c above)

    3. Select skinning and change the bindName to your entAnimatedComponent's name (step 1c above)

    4. Change the name to be unique

  3. Optional: Component uniqueness

    1. If you are running into issues, you can assign unique ids to all of your components. Go through them one by one, select their id attribute, and select "Generate new CRUID" from the context menu.

How does this work?

Thanks to ArchiveXL magic, your .app file needs only one appearance. All other appearances will be extrapolated from it!

You can use any of the existing base game hair colours, as long as the definition itself is valid.

The template file has three .app files – one of them is for your hair's default appearance, one is for the cyberware_01 appearance, and one is for the first person hair.

If you do not have a cyberware_01 appearance, you can delete this file and adjust the file path under #step-6-the-.incharactercustomization-file

If you want to add more meshes/rigs to the template .app (for example from uuhv4), you can duplicate the entSkinnedMeshComponent and the matching entAnimatedComponent from the context menu.

File Validation can help you making sure that your hair components and paths are correct.

Step 3: The .mesh files

This section will explain how ArchiveXL works its magic to pick all the right hair colours and -textures from three entries and a piece of duct tape.

If you are converting an existing hair mod, you probably already have these files.

In this case, copy appearances, materialEntries, and localMaterialInstances from the template file to your existing hair mesh.

We'll now go through everything step by step.

3.1 Appearances

To understand appearances, you can check 3d objects: .mesh files-> Step 1: Appearances. This is not necessary to complete the guide, though!

As you can see, you only need a single appearance — ArchiveXL will generate all the rest.

In our example, the first submesh uses the material @long, and the second one the material @cap.

The names must be set as follows:

<name_of_appearance>@<name_of_material> => black_carbon@long

3.2 Material definitions

To understand material definitions, you can check 3d objects: .mesh files -> Step 2: Material registry. This is not necessary to complete the guide, though!

The tutorial hair has only two materials, and three material entries (@context, @long, @cap):

You can define more materials here if you need them (please note the box below)

Now, let's look at the materials themselves.

3.3 Materials

You have to repeat this step for every mesh file in your project. Be careful, as different meshes may use different texture sets. In this case, you need an extra .mi file for them.

To understand materials, you can check 3d objects: .mesh files -> Step 3: Material definition. This is not necessary to complete the guide, though!

You can read more about @context and appearance extrapolation under Material colour extensions. This is not necessary to complete the guide, though.

@context

This is a blank container for storing contextual parameters. This is not a functioning material instance.

You can use contextual parameters in any mesh by creating a blank material named @context .

Please note the following:

  • It should always be the first materialEntries. That is, it should always be index position 0.

  • baseMaterial should always be null.

  • In values you then create a key whose value is a string of type CpuNameU64.

  • If you wish to use basegame materials as is, this string may be any context BaseMaterial in PlayerCustomizationHairFix.xl. e.g.:

  context:
    LongBaseMaterial: base\characters\common\hair\textures\hair_profiles\_master__long_bright.mi
    CapBaseMaterial: archive_xl\characters\common\hair\textures\hair_profiles\hh_025_ma__pompadour_cap.mi
  • You can find all of the fix xl configs in "Cyberpunk 2077\red4ext\plugins\ArchiveXL\Bundle\". Do not modify these files in any way, as they are required for CCXL hair implemention to function correctly.

  • If you wish to change basegame materials (e.g. path to custom hair textures), then your @context string will be a path to one of the external material instance ( .mi ) files in the project.

  • You can create a contextual parameter by doing the following:

@long

This material defines the hair cards. It points at the .mi file in your project, where the hair's textures are defined.

Since the dynamic context does not transfer to the .mi, we need to set the HairProfile here.

The {material} placeholder in the file entry will be replaced with the chunk mask name from the appearance (e.g. black_carbon).

@cap

This material defines the hair cap (the stubbles on the scalp). It points at the .mi file in your project, where the scalp's textures are defined.

Since the dynamic context does not transfer to the .mi, we need to set the GradientMap here. Omitting this will lead to the hair cap looking way darker than it's supposed to.

Step 4: The .mi files

The .mi file and the @context are required for ArchiveXL character creator extensions. Without a .mi file, you won't have e.g. extra hair colours (e.g. Hair Profiles CCXL)

With the exception of the hair cap, the .mi file is a completely normal material tempate file (link not necessary for understanding this guide).

The hair cap base material is included within ArchiveXL. If you aren't using one, you don't need to know any of this — just move all properties without dynamic properties from the .mesh file into your .mi.

Step 5: The translation entry

Open the included .json file, and make sure to change the entries according to your needs.

There are two translation entries, because this tutorial assumes that you want to name the cyberware_01 variant differently.

For an explanation of what is what, keep reading.

key
value
explanation

femaleVariant

Your First Hair

maleVariant

leave it blank

If no value is found, then femaleVariant acts as default

primaryKey

0

Will be generated by ArchiveXL, leave it alone

secondaryKey

UI-Customization-your_first_hair

Used in the .inkcharactercustomization file to set your hair's entry name

Step 6: The .inkcharactercustomization file

Here is where everything connects to each other.

For more information about this, see .inkcharactercustomization: CC options

Open the file, we will look at the entries now.

6.1 headGroups

These entries create character creator additions, while the CustomizationOptions define them (think of a materialDefinition and a materialInstance in a .mesh file).

6.2 gameUiSwitcherInfos

Let's take a look at the headCustomizationOptions. The first to entries of the type gameuiSwitcherInfo add our new hair to Cyberpunk's character creator menu, so that they show up when you scroll through the hairs.

The first entry

  • link: Targets one of the headGroups entries

  • names: Contains the headGroup's options

If you want to use a different mesh when cyberware_01 is enabled, you will have to cut "hairstyle" from the link in the first entry and instead put it in name to have two visibly distinct meshes. Otherwise you'll only have one mesh visible.

The second entry: hairstyle_cyberware

This entry defines the hairstyle for cyberware_01.

6.3 gameUiAppearanceInfos

For more information on this, see .inkcharactercustomization: CC options -> gameuiAppearanceInfo. This is not necessary for the purpose of this guide!

The template inkcc has three gameUiAppearanceInfos, one for your hair, one for the cyberware_01 variant, and one for FPP.

If you do not have an extra appearance for cyberware_01, you can re-use the default hair .app file.

Make sure to adjust the paths to your corresponding .app file:

Step 7: The .xl file

From your project's resource directory, open the .archive.xl file that you created in the previous guide. Add the following lines at the bottom (make sure that there are no leading spaces):

customizations:
  female: your_modder_name\ccxl\your_first_addition\_pwa.inkcharcustomization
localization:
  onscreens:
    en-us: your_modder_name\ccxl\your_first_addition\localization\your_first_hair_wa__local.json
resource:
  scope:
    player_wa_hair.app:
      - your_modder_name\ccxl\your_first_addition\appearances\your_first_hair_wa.app
      - your_modder_name\ccxl\your_first_addition\appearances\your_first_hair_wa_cyberware.app
      - your_modder_name\ccxl\your_first_addition\appearances\fpp\your_first_hair_wa_fpp.app
    player_wa_hair.mesh:
      - your_modder_name\ccxl\your_first_addition\meshes\your_first_hair_wa.mesh
      - your_modder_name\ccxl\your_first_addition\meshes\your_first_hair_wa_cyberware.mesh
TODO: What does this do?

It just works. Adjust the paths!

Step 8: Renaming and moving

Now it's time to custompath your project.

Troubleshooting

Hair colour extensions don't work on my hair!

Most likely, you screwed up the names of your material definitions. They must be exactly as ArchiveXL expects them to be. Go back to 3.2 Material definitions and double-check everything.

If that doesn't help, check the log (see My hair is always black!)

My hair is always black!

That happens when the material patching/expansion didn't work. Search the ArchiveXL log for the name of the broken hair mesh. Most likely, there is a warning or an error that you can fix.

I have duplicate entry in hairstyles options!

This happens due to having a different localizedName forcyberware_hairstyle switcher that's inside the.inkcc file. For exampleUI-Customization-your_first_hair in the blank switcher, and UI-Customization-your_first_hair_cyberware in the cyberware_hairstyle switcher.

If you want to have a unique hairstyle mesh when cyberware_01 is enabled refer to 6.2 gameUiSwitcherInfos, specifically the hint about link and name.

Last updated

Was this helpful?