Setting up a ModuleControllableEmissive - KSPSnark/IndicatorLights GitHub Wiki

Before you begin

Before you can set up a ModuleControllableEmissive, you need to have a mesh (or set of meshes) on your part which the ModuleControllableEmissive will point to.

If you haven't done that already, here's how to find or set up such a mesh.

What to do

A ModuleControllableEmissive has just two properties which you must set, in order for it to be usable:

  • target: The name of the mesh (or meshes) whose colors this module will set.
    • This name has to exactly match the name of the mesh on the part. See notes below.
    • If you don't know the name of the mesh, the IndicatorLights debug console can help you with this in-game.
    • If there are multiple meshes with the same name, by default this will drive all of them.
    • However, if there are multiple meshes with the same name and you want to drive only some of them, there's a way to do that; see below.
  • emissiveName: A unique identifier for this emissive, which controllers will use to reference it.
    • This can be whatever you like; just pick something readable. Its only consumer will be the ModuleEmissiveControllers that you add.
  • There's also an optional property, renderType, which can be used to work with Unity shaders other than emissive ones. See Working with different shader types section, below.

The exact syntax of the target string could be one of two types, depending on whether the mesh is a "native" piece of the part itself, or whether it was "bolted on" via ModuleManager config.

  • If it's a "native" mesh: then target will just be the simple name of the mesh, with no pathing or hierarchy information.
    • Here's the BL-01 Indicator Light config as an example.
    • Note that the target value is simply "light", with no path information. That's because that's the name of the mesh on the part.
  • If it's a "bolted-on" mesh via ModuleManager: then target will be the full path to the mesh file from your GameData folder, without the .mu extension.
    • Here's the Z400 battery config as an example.
    • Note that the target value is "IndicatorLights/Meshes/nubbinLamp", since this is an "add-on" mesh via ModuleManager.

Example of a ModuleControllableEmissive:

MODULE {
    name = ModuleControllableEmissive

    // Full path, because this example is for a MM add-on mesh
    target = IndicatorLights/Meshes/nubbinLamp 

    // The "name" of this module. Controllers use this for identifying it.
    emissiveName = indicator
}

How to reference multiple meshes (with the same name) from one ModuleControllableEmissive

Maybe your part has several meshes on it, and you want them all to turn on and off together as a single unit. For example, here's the IndicatorLights config for the Z4K battery. This battery has four meshes, spaced around the rim of the battery. They all turn on and off together.

That's easy: in this case, all of those meshes happen to have exactly the same name as each other. Therefore, we only need a single ModuleControllableEmissive to drive them.

That's because by default, a ModuleControllableEmissive will drive ALL meshes that have the same name as the target value.

(If you want it not to do that... you can limit which meshes it uses via an index specifier, see below.)


How to reference specific meshes, when there are lots of them with the same name

Here's an interesting case: see how the indicator lights are set up in the ISRU converter config.

This part has 12 meshes that all have exactly the same name. Each of them looks like this (just the position and rotation change from one mesh to the next):

MODEL
{
    model = IndicatorLights/Meshes/nubbinLamp
    scale = 0.8, 0.8, 0.7
    position = -0.2, 0.1, -1.078
    rotation = 0, 180, 0
}

Unlike the case of the Z4K battery described above, however, they do not all function together as a single unit. They're in four groups of three, with each group-of-three functioning together as a unit.

That means we need to set up one ModuleEmissiveController for each group-of-meshes-that-act-together-as-a-unit. In other words, we will need four ModuleEmissiveControllers. But how do we tell each one which of the 12 meshes it should connect to?

We do that with an index specifier at the end of the target, like this:

MODULE {
    name = ModuleControllableEmissive
    target = IndicatorLights/Meshes/nubbinLamp:0,4,8
    emissiveName = LFO
}

Note that :0,4,8 tacked on to the end of the target value. What that means is "only apply to the IndicatorLights/Meshes/nubbinLamp at indices 0, 4, and 8".

Note that this means that order is important for the meshes. The "0" in the index specifier means "the first mesh of that name found on the model". In the case of "native" meshes that are built into the part itself, this will be the order that they're arranged in the .mu file. In the case of meshes that are added to the part via ModuleManager config (such as this example), the order of the meshes will be the order in which they appear in the .cfg file.


What if I want one ModuleControllableEmissive to drive multiple meshes with different names?

Suppose you have a part where you've added several meshes with different names, and you want them all to function together as a single unit. How do you do that?

Well, you can't actually do it with a single ModuleControllableEmissive, since each such module can only specify one target name. However, you can accomplish the same effect thus:

  • Have one ModuleControllableEmissive for each of your different mesh names. Set the target value appropriately for each one.
  • Give those ModuleControllableEmissives the same emissiveName.

For an example of this design in action, see the Clamp-O-Tron Sr. docking port config:

  • There are meshes with two different names, IndicatorLights/Meshes/squareLamp and IndicatorLights/Meshes/squareLamp2. (Three of each, in fact.)
  • However, we want all six of these meshes to function together as a single unit.
  • Therefore, there's one ModuleControllableEmissive for the three squareLamp meshes, and one ModuleControllableEmissive for the threesquareLamp2 meshes.
  • Both of those ModuleControllableEmissives have the same emissiveName = indicator.
  • That accomplishes what we want, because any ModuleEmissiveController that we later set up (see below) to point at the emissive named indicator will automatically drive every ModuleControllableEmissive with that name.

Working with different shader types

By default, ModuleControllableEmissive sets the emissive color on the target mesh or meshes (i.e., identified by the Unity shader property ID _EmissiveColor).

However, if you're working with a different shader and need to set the tint color instead (shader property ID _TintColor), you can do so. Diffuse color can also be controlled (shader property ID _Color).

ModuleControllableEmissive has an optional property, renderType, which you can set to emissive, tint, or main. By default, it's set to emissive. Just add renderType = tint or renderType = main to set a different color type instead.


Help! It's not working! How do I debug this?

The IndicatorLights debug console can help understand in-game what's going on with your config. It lets you display all the ModuleControllableEmissives for a part, and what mesh each one is pointing at. It also lets you display all the meshes on a part, so you know what name to use in your ModuleControllableEmissive.


What next?

After you've got your ModuleControllableEmissive (or multiple ones) ready, you'll want to set up a ModuleEmissiveController to point at it.