├── .gitignore
├── screenshots
├── sas.png
├── crew.png
├── isru.png
├── Mk1Pod.png
├── Mk2Can.png
├── antennas.png
├── robotics.png
├── scanning.png
├── science.png
├── batteries.png
├── fuel cell.png
├── telescope.png
├── MakingHistory.png
├── blinkenlight.png
├── docking ports.png
├── magnetometer.png
├── turn signals.gif
├── emissive arrays.gif
├── fuel cell array.png
├── reaction wheels.png
└── data transmission.gif
├── diagrams
├── bl01diagram.png
├── simpleDiagram.png
└── complexDiagram.png
├── files
├── Meshes
│ ├── White.png
│ ├── z100lamp.mu
│ ├── Lightbulb.png
│ ├── nubbinLamp.mu
│ ├── squareLamp.mu
│ └── squareLamp2.mu
├── ModuleManager.4.2.3.dll
├── Parts
│ ├── fuelCells
│ │ ├── White.png
│ │ ├── Lightbulb.png
│ │ ├── arrayIndicatorModel.mu
│ │ ├── rectangularIndicatorModel.mu
│ │ ├── FuelCellArrayIndicator.cfg
│ │ └── FuelCellIndicator.cfg
│ ├── indicatorLightSmall
│ │ ├── Bezel.png
│ │ ├── White.png
│ │ ├── model.mu
│ │ ├── Lightbulb.png
│ │ └── indicatorLightSmall.cfg
│ ├── cones
│ │ └── avionicsCone.cfg
│ ├── scanners
│ │ ├── surveyScanner.cfg
│ │ └── surfaceScanner.cfg
│ ├── dockingPorts
│ │ ├── inflatableAirlock.cfg
│ │ ├── smallPort.cfg
│ │ └── mediumPort.cfg
│ ├── robotics
│ │ └── kal1000.cfg
│ ├── science
│ │ ├── scienceBox.cfg
│ │ ├── gravioli.cfg
│ │ ├── barometer.cfg
│ │ ├── magnetometer.cfg
│ │ ├── variometer.cfg
│ │ ├── thermometer.cfg
│ │ ├── accelerometer.cfg
│ │ ├── telescope.cfg
│ │ ├── goo.cfg
│ │ └── scienceJr.cfg
│ ├── crewable
│ │ ├── mk1cockpit.cfg
│ │ ├── mk1cockpitInline.cfg
│ │ ├── mk1pod_v2.cfg
│ │ ├── kv1pod.cfg
│ │ ├── mk1cabin.cfg
│ │ ├── cupola.cfg
│ │ ├── mk1can.cfg
│ │ ├── scienceLab.cfg
│ │ ├── mk2cockpit.cfg
│ │ └── mk2cockpitInline.cfg
│ ├── batteries
│ │ ├── Z400Indicator.cfg
│ │ ├── Z100Indicator.cfg
│ │ ├── Z200Indicator.cfg
│ │ ├── Z1KIndicator.cfg
│ │ └── Z4KIndicator.cfg
│ ├── reactionWheels
│ │ ├── smallReactionWheel.cfg
│ │ ├── largeReactionWheel.cfg
│ │ └── mediumReactionWheel.cfg
│ ├── antennas
│ │ ├── hg55.cfg
│ │ ├── smallRelayDish.cfg
│ │ ├── mediumRelayDish.cfg
│ │ ├── communotron16S.cfg
│ │ ├── largeRelayDish.cfg
│ │ ├── 88-88.cfg
│ │ ├── communotron16.cfg
│ │ ├── dtsM1.cfg
│ │ └── hg5.cfg
│ └── obsolete
│ │ └── mk1pod.cfg
├── Agencies
│ ├── Blinkenlights.png
│ └── Agents.cfg
├── Flags
│ └── Blinkenlights-Flag.png
├── Patches
│ ├── IndicatorLights_TextureReplacer.cfg
│ ├── IndicatorLights_TweakScale.cfg
│ └── IndicatorLights_KIS.cfg
├── Config
│ └── IndicatorLights.cfg
└── ModuleManagerLicense.md
├── release
├── IndicatorLights-1.0.zip
├── IndicatorLights-1.1.zip
├── IndicatorLights-1.2.zip
├── IndicatorLights-1.3.zip
├── IndicatorLights-1.4.zip
├── IndicatorLights-1.5.zip
├── IndicatorLights-1.6.zip
├── IndicatorLights-1.7.zip
├── IndicatorLights-1.8.zip
├── IndicatorLights-1.2.1.zip
├── IndicatorLights-1.2.10.zip
├── IndicatorLights-1.2.11.zip
├── IndicatorLights-1.2.12.zip
├── IndicatorLights-1.2.2.zip
├── IndicatorLights-1.2.3.zip
├── IndicatorLights-1.2.4.zip
├── IndicatorLights-1.2.5.zip
├── IndicatorLights-1.2.6.zip
├── IndicatorLights-1.2.7.zip
├── IndicatorLights-1.2.8.zip
├── IndicatorLights-1.2.9.zip
├── IndicatorLights-1.3.1.zip
├── IndicatorLights-1.4.1.zip
├── IndicatorLights-1.4.2.zip
├── IndicatorLights-1.8.1.zip
├── IndicatorLights-1.8.2.zip
├── IndicatorLights-1.8.3.zip
└── assemble_release
├── prerelease
├── IndicatorLights-0.1.zip
├── IndicatorLights-0.2.zip
├── IndicatorLights-0.3.zip
├── IndicatorLights-0.4.zip
├── IndicatorLights-0.5.zip
├── IndicatorLights-0.6.zip
├── IndicatorLights-0.7.zip
├── IndicatorLights-0.8.zip
├── IndicatorLights-0.9.zip
├── IndicatorLights-0.10.zip
├── IndicatorLights-0.11.zip
├── IndicatorLights-0.7.1.zip
├── IndicatorLights-0.9.1.zip
├── IndicatorLights-0.10.1.zip
└── assemble_release
├── src
├── IScalar.cs
├── ModuleScienceContainerIndicator.cs
├── IToggle.cs
├── GlobalSettings.cs
├── IColorSource.cs
├── ScalarIDField.cs
├── StaticField.cs
├── ToggleIDField.cs
├── Vessels.cs
├── ColorSourceIDField.cs
├── ModuleScienceDataIndicator.cs
├── IndicatorLights.sln
├── ExperimentalController.cs
├── Console
│ ├── HelpCommand.cs
│ ├── LightsEnabledCommand.cs
│ └── PartsCommand.cs
├── Properties
│ └── AssemblyInfo.cs
├── ModuleDockingCrossfeedIndicator.cs
├── RateLimiter.cs
├── VesselScienceTracker.cs
├── ScienceValue.cs
├── ModuleEmissiveArrayController.cs
├── ModuleResourceEnabledIndicator.cs
├── ModuleSourceIndicator.cs
├── RenderType.cs
├── ModuleDockingStateIndicator.cs
├── ModuleBiomeScannerIndicator.cs
├── Logging.cs
├── PartSearchStrategy.cs
├── ModuleCrewIndicatorToggle.cs
├── Loader.cs
├── ModuleDataTransmitterIndicator.cs
├── ModuleBooleanIndicator.cs
├── ModuleEmissiveController.cs
├── ColorSourceArray.cs
├── Extensions.cs
└── ModuleResourceIndicator.cs
├── README.md
└── examples
├── VesselControlLevel.cfg
├── AttachableResourceIndicator.cfg
├── RandomLights.cfg
├── VesselSituation.cfg
└── ArbitraryFieldInputs.cfg
/.gitignore:
--------------------------------------------------------------------------------
1 | src/.vs
2 | src/bin
3 | src/obj
4 |
--------------------------------------------------------------------------------
/screenshots/sas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/sas.png
--------------------------------------------------------------------------------
/screenshots/crew.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/crew.png
--------------------------------------------------------------------------------
/screenshots/isru.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/isru.png
--------------------------------------------------------------------------------
/diagrams/bl01diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/diagrams/bl01diagram.png
--------------------------------------------------------------------------------
/files/Meshes/White.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Meshes/White.png
--------------------------------------------------------------------------------
/files/Meshes/z100lamp.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Meshes/z100lamp.mu
--------------------------------------------------------------------------------
/screenshots/Mk1Pod.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/Mk1Pod.png
--------------------------------------------------------------------------------
/screenshots/Mk2Can.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/Mk2Can.png
--------------------------------------------------------------------------------
/screenshots/antennas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/antennas.png
--------------------------------------------------------------------------------
/screenshots/robotics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/robotics.png
--------------------------------------------------------------------------------
/screenshots/scanning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/scanning.png
--------------------------------------------------------------------------------
/screenshots/science.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/science.png
--------------------------------------------------------------------------------
/diagrams/simpleDiagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/diagrams/simpleDiagram.png
--------------------------------------------------------------------------------
/files/Meshes/Lightbulb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Meshes/Lightbulb.png
--------------------------------------------------------------------------------
/files/Meshes/nubbinLamp.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Meshes/nubbinLamp.mu
--------------------------------------------------------------------------------
/files/Meshes/squareLamp.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Meshes/squareLamp.mu
--------------------------------------------------------------------------------
/screenshots/batteries.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/batteries.png
--------------------------------------------------------------------------------
/screenshots/fuel cell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/fuel cell.png
--------------------------------------------------------------------------------
/screenshots/telescope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/telescope.png
--------------------------------------------------------------------------------
/diagrams/complexDiagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/diagrams/complexDiagram.png
--------------------------------------------------------------------------------
/files/Meshes/squareLamp2.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Meshes/squareLamp2.mu
--------------------------------------------------------------------------------
/files/ModuleManager.4.2.3.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/ModuleManager.4.2.3.dll
--------------------------------------------------------------------------------
/screenshots/MakingHistory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/MakingHistory.png
--------------------------------------------------------------------------------
/screenshots/blinkenlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/blinkenlight.png
--------------------------------------------------------------------------------
/screenshots/docking ports.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/docking ports.png
--------------------------------------------------------------------------------
/screenshots/magnetometer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/magnetometer.png
--------------------------------------------------------------------------------
/screenshots/turn signals.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/turn signals.gif
--------------------------------------------------------------------------------
/files/Parts/fuelCells/White.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/fuelCells/White.png
--------------------------------------------------------------------------------
/release/IndicatorLights-1.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.0.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.1.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.3.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.4.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.4.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.5.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.5.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.6.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.6.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.7.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.7.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.8.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.8.zip
--------------------------------------------------------------------------------
/screenshots/emissive arrays.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/emissive arrays.gif
--------------------------------------------------------------------------------
/screenshots/fuel cell array.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/fuel cell array.png
--------------------------------------------------------------------------------
/screenshots/reaction wheels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/reaction wheels.png
--------------------------------------------------------------------------------
/files/Agencies/Blinkenlights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Agencies/Blinkenlights.png
--------------------------------------------------------------------------------
/files/Flags/Blinkenlights-Flag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Flags/Blinkenlights-Flag.png
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.1.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.2.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.3.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.4.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.4.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.5.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.5.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.6.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.6.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.7.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.7.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.8.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.8.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.9.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.9.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.1.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.10.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.10.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.11.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.11.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.12.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.12.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.2.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.3.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.4.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.4.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.5.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.5.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.6.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.6.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.7.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.7.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.8.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.8.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.2.9.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.2.9.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.3.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.3.1.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.4.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.4.1.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.4.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.4.2.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.8.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.8.1.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.8.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.8.2.zip
--------------------------------------------------------------------------------
/release/IndicatorLights-1.8.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/release/IndicatorLights-1.8.3.zip
--------------------------------------------------------------------------------
/screenshots/data transmission.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/screenshots/data transmission.gif
--------------------------------------------------------------------------------
/files/Parts/fuelCells/Lightbulb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/fuelCells/Lightbulb.png
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.10.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.10.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.11.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.11.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.7.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.7.1.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.9.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.9.1.zip
--------------------------------------------------------------------------------
/prerelease/IndicatorLights-0.10.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/prerelease/IndicatorLights-0.10.1.zip
--------------------------------------------------------------------------------
/files/Parts/indicatorLightSmall/Bezel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/indicatorLightSmall/Bezel.png
--------------------------------------------------------------------------------
/files/Parts/indicatorLightSmall/White.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/indicatorLightSmall/White.png
--------------------------------------------------------------------------------
/files/Parts/indicatorLightSmall/model.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/indicatorLightSmall/model.mu
--------------------------------------------------------------------------------
/files/Patches/IndicatorLights_TextureReplacer.cfg:
--------------------------------------------------------------------------------
1 | @TextureReplacer:AFTER[TextureReplacer]
2 | {
3 | keepLoaded = ^IndicatorLights/
4 | }
5 |
--------------------------------------------------------------------------------
/files/Parts/fuelCells/arrayIndicatorModel.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/fuelCells/arrayIndicatorModel.mu
--------------------------------------------------------------------------------
/files/Parts/indicatorLightSmall/Lightbulb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/indicatorLightSmall/Lightbulb.png
--------------------------------------------------------------------------------
/files/Parts/fuelCells/rectangularIndicatorModel.mu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KSPSnark/IndicatorLights/HEAD/files/Parts/fuelCells/rectangularIndicatorModel.mu
--------------------------------------------------------------------------------
/src/IScalar.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// A simple interface for controllers that work off a scalar quatity (e.g. resource level).
5 | ///
6 | public interface IScalar
7 | {
8 | double ScalarValue { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ModuleScienceContainerIndicator.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | class ModuleScienceContainerIndicator : ModuleScienceDataIndicatorBase
4 | {
5 | // Nothing to see here, folks... does nothing other than specialize the base
6 | // class for ModuleScienceContainer.
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/files/Patches/IndicatorLights_TweakScale.cfg:
--------------------------------------------------------------------------------
1 | // Thanks to Sharpy in the KSP forums for providing both the feature
2 | // request and the implementation technique!
3 |
4 | @PART[indicatorLightSmall]:AFTER[IndicatorLights]:NEEDS[TweakScale]
5 | {
6 | MODULE {
7 | name = TweakScale
8 | type = free
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/IToggle.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// A simple interface for toggle controllers.
5 | ///
6 | public interface IToggle
7 | {
8 | ///
9 | /// The current on/off status of the toggle.
10 | ///
11 | bool ToggleStatus { get; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/files/Agencies/Agents.cfg:
--------------------------------------------------------------------------------
1 | AGENT
2 | {
3 | name = Blinkenlights LLC
4 | title = Blinkenlights LLC
5 |
6 | description = Give us your tired old technology and we'll glitz it up with distracting glowy things!
7 |
8 | logoURL = IndicatorLights/Agencies/Blinkenlights
9 |
10 | // mentalities
11 | mentality = Commercial
12 | mentality = Industrial
13 | mentality = Economic
14 | }
15 |
--------------------------------------------------------------------------------
/prerelease/assemble_release:
--------------------------------------------------------------------------------
1 | echo Creating pre-release file structure
2 | mkdir -p GameData/IndicatorLights
3 | cp ../files/ModuleManager.*.dll GameData
4 | cp ../files/ModuleManagerLicense.md GameData
5 | cp ../files/changelog.txt GameData/IndicatorLights
6 | cp ../src/bin/Release/IndicatorLights.dll GameData/IndicatorLights
7 | cp ../LICENSE GameData/IndicatorLights
8 | cp ../README.md GameData/IndicatorLights
9 | cp -R ../files/Agencies GameData/IndicatorLights
10 | cp -R ../files/Flags GameData/IndicatorLights
11 | cp -R ../files/Meshes GameData/IndicatorLights
12 | cp -R ../files/Parts GameData/IndicatorLights
13 | cp -r ../files/Patches GameData/IndicatorLights
14 | echo Done.
15 |
--------------------------------------------------------------------------------
/files/Config/IndicatorLights.cfg:
--------------------------------------------------------------------------------
1 | IndicatorLights {
2 | // Default color choices for each kerbal class. This is the color that gets used
3 | // for crew indicators on any part that doesn't override the colors with something
4 | // specific.
5 | //
6 | // Note that IndicatorLights has integrated support for the Community Trait Icons
7 | // mod. If Community Trait Icons is installed, then IndicatorLights will use the
8 | // colors that come from there, overriding any colors specified here.
9 | CrewIndicatorDefaultColors {
10 | Pilot = $CrewPilot
11 | Engineer = $CrewEngineer
12 | Scientist = $CrewScientist
13 | Tourist = $CrewTourist
14 | Unknown = $Unknown
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/GlobalSettings.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Stores important settings that apply across the whole mod, and which can be modified
5 | /// at run time.
6 | ///
7 | internal static class GlobalSettings
8 | {
9 | private static bool isEnabled = true;
10 |
11 | ///
12 | /// Gets or sets whether all lights everywhere are enabled, across the module.
13 | /// True by default. When set to false, all lights go dark.
14 | ///
15 | public static bool IsEnabled
16 | {
17 | get { return isEnabled; }
18 | set { isEnabled = value; }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/IColorSource.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Interface for objects that can provide a color.
7 | ///
8 | public interface IColorSource
9 | {
10 | ///
11 | /// Whether a color is currently available.
12 | ///
13 | bool HasColor { get; }
14 |
15 | ///
16 | /// Current color. Do not call this unless HasColor returns true.
17 | ///
18 | Color OutputColor { get; }
19 |
20 | ///
21 | /// Gets the ID of this source.
22 | ///
23 | string ColorSourceID { get; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/release/assemble_release:
--------------------------------------------------------------------------------
1 | echo Creating release file structure
2 | mkdir -p GameData/IndicatorLights
3 | cp ../files/ModuleManager.*.dll GameData
4 | cp ../files/ModuleManagerLicense.md GameData
5 | cp ../files/changelog.txt GameData/IndicatorLights
6 | cp ../src/bin/Release/IndicatorLights.dll GameData/IndicatorLights
7 | cp ../LICENSE GameData/IndicatorLights
8 | cp ../README.md GameData/IndicatorLights
9 | cp -R ../files/Agencies GameData/IndicatorLights
10 | cp -R ../files/Config GameData/IndicatorLights
11 | cp -R ../files/Flags GameData/IndicatorLights
12 | cp -R ../files/Meshes GameData/IndicatorLights
13 | cp -R ../files/Parts GameData/IndicatorLights
14 | cp -r ../files/Patches GameData/IndicatorLights
15 | echo Done.
16 |
--------------------------------------------------------------------------------
/files/ModuleManagerLicense.md:
--------------------------------------------------------------------------------
1 | ModuleManager
2 | =============
3 |
4 |
5 | Original (c) from Ialdabaoth ( https://github.com/Ialdabaoth )
6 |
7 | Modified by // Modifications by // Maintained by sarbian ( https://github.com/sarbian )
8 |
9 |
10 | The original licence requirement was:
11 |
12 | ---
13 |
14 | under a CC share-alike license. Anyone is free to do anything they like with ModuleManager's source, with two caveats:
15 |
16 | 1. You credit me as the original creator that your code is based on
17 | 2. You make it ABSOLUTELY CLEAR that your code is not the original ModuleManager, and that any problems that people have with your fork should be taken up with YOU, not me.
18 |
19 | ---
20 |
21 |
22 | THIS IS NOT THE ORIGINAL MODULEMANAGER CODE.
23 |
24 | Do not bother Ialdabaoth about any problems with it.
25 |
--------------------------------------------------------------------------------
/src/ScalarIDField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Used for decorating module properties that are intended to be parsed as scalar IDs.
7 | ///
8 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
9 | class ScalarIDField : Attribute
10 | {
11 | ///
12 | /// Gets whether the specified field is a scalar ID field.
13 | ///
14 | ///
15 | ///
16 | public static bool Is(BaseField field)
17 | {
18 | return field.FieldInfo.IsDefined(typeof(ScalarIDField), true)
19 | && (typeof(string).IsAssignableFrom(field.FieldInfo.FieldType));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/StaticField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 |
4 | namespace IndicatorLights
5 | {
6 | ///
7 | /// Used for decorating module properties that are intended to be used as static inputs.
8 | ///
9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
10 | class StaticField : Attribute
11 | {
12 | ///
13 | /// Gets whether the specified field is a scalar field.
14 | ///
15 | ///
16 | ///
17 | public static bool Is(FieldInfo field)
18 | {
19 | return field.IsDefined(typeof(StaticField), true)
20 | && (typeof(double).IsAssignableFrom(field.FieldType));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ToggleIDField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Used for decorating module properties that are intended to be parsed as toggle IDs.
7 | ///
8 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
9 | class ToggleIDField : Attribute
10 | {
11 | ///
12 | /// Gets whether the specified field is a scalar ID field.
13 | ///
14 | ///
15 | ///
16 | public static bool Is(BaseField field)
17 | {
18 | return field.FieldInfo.IsDefined(typeof(ToggleIDField), true)
19 | && (typeof(string).IsAssignableFrom(field.FieldInfo.FieldType));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Vessels.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | static class Vessels
4 | {
5 | ///
6 | /// Get the current biome of the ship. Returns null if none.
7 | ///
8 | ///
9 | ///
10 | public static string GetCurrentBiome(this Vessel vessel)
11 | {
12 | if (vessel == null) return null;
13 | double lat = ResourceUtilities.Deg2Rad((vessel.latitude + 180.0 + 90.0) % 180.0 - 90.0);
14 | double lon = ResourceUtilities.Deg2Rad((vessel.longitude + 360.0 + 180.0) % 360.0 - 180.0);
15 | CBAttributeMapSO.MapAttribute biome = ResourceUtilities.GetBiome(lat, lon, vessel.mainBody);
16 | return (biome == null) ? null : biome.name;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ColorSourceIDField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Used for decorating module properties that are intended to be parsed as color source IDs.
7 | ///
8 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
9 | public class ColorSourceIDField : Attribute
10 | {
11 | ///
12 | /// Gets whether the specified field is a color source ID field.
13 | ///
14 | ///
15 | ///
16 | public static bool Is(BaseField field)
17 | {
18 | return field.FieldInfo.IsDefined(typeof(ColorSourceIDField), true)
19 | && (typeof(string).IsAssignableFrom(field.FieldInfo.FieldType));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## What it does
2 |
3 | Adds various helpful LED "indicators" to enhance your ships. Broadly speaking, these fall into two categories:
4 |
5 | * **Standalone parts:** radially attachable LED lights with customizable colors, which can be toggled on/off with action groups.
6 | * **Enhancements to existing parts:** add LEDs to stock parts to provide a visible, automatic indication of part status (such as whether a fuel cell is on or off).
7 |
8 | For details (either as a player or as a modder), please see the **[IndicatorLights wiki](https://github.com/KSPSnark/IndicatorLights/wiki)**.
9 |
10 |
11 | ## How to install
12 |
13 | Unzip the contents of "GameData" to your GameData folder, same as with most mods. (Note, includes ModuleManager.)
14 |
15 |
16 | ## It's not done yet!
17 |
18 | I'm still working on adding features and content. Please see the wiki to stay up to date!
19 |
--------------------------------------------------------------------------------
/src/ModuleScienceDataIndicator.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Indicates whether a science experiment contains data or not. Has the ability
5 | /// to show different colors depending on the value of the science data.
6 | ///
7 | class ModuleScienceDataIndicator : ModuleScienceDataIndicatorBase
8 | {
9 | ///
10 | /// Indicates the experiment which corresponds to this indicator (mainly useful
11 | /// for cases where one part may have multiple science experiments on it).
12 | /// Optional field. If null or empty, will simply use the first science experiment
13 | /// found on the part.
14 | ///
15 | [KSPField]
16 | public string experimentID = null;
17 |
18 | protected override bool IsSource(ModuleScienceExperiment candidate)
19 | {
20 | return string.IsNullOrEmpty(experimentID) || (experimentID.Equals(candidate.experimentID));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/IndicatorLights.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IndicatorLights", "IndicatorLights.csproj", "{8448DE0D-400E-4F55-815E-FDF996F6BC4B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {8448DE0D-400E-4F55-815E-FDF996F6BC4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {8448DE0D-400E-4F55-815E-FDF996F6BC4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {8448DE0D-400E-4F55-815E-FDF996F6BC4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {8448DE0D-400E-4F55-815E-FDF996F6BC4B}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/files/Parts/cones/avionicsCone.cfg:
--------------------------------------------------------------------------------
1 | // Instrument the avionics nosecone to indicate the current SAS mode.
2 |
3 | @PART[avionicsNoseCone]:FOR[IndicatorLights]
4 | {
5 | @description ^= :(.)$:$0 Indicator light shows current SAS status.:
6 |
7 | //-------------------------------------------------------------------------
8 | // INDICATOR MESHES
9 | //-------------------------------------------------------------------------
10 | MODEL
11 | {
12 | model = IndicatorLights/Meshes/nubbinLamp
13 | scale = 1.5, 1.5, 2
14 | position = 0, 0.137, -0.227
15 | rotation = -90, 0, 0
16 | }
17 |
18 | //-------------------------------------------------------------------------
19 | // CONTROLLABLE EMISSIVES
20 | //-------------------------------------------------------------------------
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/nubbinLamp
24 | emissiveName = indicator
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLERS
29 | //-------------------------------------------------------------------------
30 | MODULE {
31 | name = ModuleSasIndicator
32 | emissiveName = indicator
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/ExperimentalController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Used for designating controllers that are considered "experimental": i.e. subject to change
7 | /// or even deletion without notice, so nobody should be building code or config that depends
8 | /// on it if they care what happens to it.
9 | ///
10 | /// The purpose is to allow "pre-releasing" early rough drafts of new ideas, to give people
11 | /// a chance to play around with it and provide feedback, while making clear that it's
12 | /// subject to breaking changes without warning.
13 | ///
14 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
15 | public class ExperimentalController : Attribute
16 | {
17 | ///
18 | /// Gets whether the specified controller is of an experimental type.
19 | ///
20 | ///
21 | ///
22 | public static bool Is(ModuleEmissiveControllerBase controller)
23 | {
24 | return controller.GetType().IsDefined(typeof(ExperimentalController), true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/files/Parts/fuelCells/FuelCellArrayIndicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds an LED indicator to the fuel cell array.
2 |
3 | @PART[FuelCellArray]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status light!:
5 |
6 | //-------------------------------------------------------------------------
7 | // INDICATOR MESHES
8 | //-------------------------------------------------------------------------
9 |
10 | MODEL
11 | {
12 | model = IndicatorLights/Parts/fuelCells/arrayIndicatorModel
13 | position = -0.24708, -0.41497, 0.23743
14 | rotation = 0, 90, 0
15 | }
16 |
17 |
18 | //-------------------------------------------------------------------------
19 | // CONTROLLABLE EMISSIVES
20 | //-------------------------------------------------------------------------
21 |
22 | MODULE {
23 | name = ModuleControllableEmissive
24 | target = IndicatorLights/Parts/fuelCells/arrayIndicatorModel
25 | emissiveName = indicator
26 | }
27 |
28 |
29 | //-------------------------------------------------------------------------
30 | // CONTROLLERS
31 | //-------------------------------------------------------------------------
32 |
33 | MODULE {
34 | name = ModuleConverterIndicator
35 | converterName = Fuel Cell
36 | emissiveName = indicator
37 | }
38 | }
--------------------------------------------------------------------------------
/files/Parts/fuelCells/FuelCellIndicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds an LED indicator to the fuel cell.
2 |
3 | @PART[FuelCell]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status light!:
5 |
6 | //-------------------------------------------------------------------------
7 | // INDICATOR MESHES
8 | //-------------------------------------------------------------------------
9 |
10 | MODEL
11 | {
12 | model = IndicatorLights/Parts/fuelCells/rectangularIndicatorModel
13 | scale = 0.11077, 0.8, 0.5
14 | position = -0.19, 0, -0.07
15 | rotation = 0, 180, 0
16 | }
17 |
18 |
19 | //-------------------------------------------------------------------------
20 | // CONTROLLABLE EMISSIVES
21 | //-------------------------------------------------------------------------
22 |
23 | MODULE {
24 | name = ModuleControllableEmissive
25 | target = IndicatorLights/Parts/fuelCells/rectangularIndicatorModel
26 | emissiveName = indicator
27 | }
28 |
29 |
30 | //-------------------------------------------------------------------------
31 | // CONTROLLERS
32 | //-------------------------------------------------------------------------
33 |
34 | MODULE {
35 | name = ModuleConverterIndicator
36 | converterName = Fuel Cell
37 | emissiveName = indicator
38 | }
39 | }
--------------------------------------------------------------------------------
/files/Parts/scanners/surveyScanner.cfg:
--------------------------------------------------------------------------------
1 | // Adds an LED indicator to the survey scanner unit.
2 |
3 | @PART[SurveyScanner]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 LED indicates operational status.:
5 |
6 | //-------------------------------------------------------------------------
7 | // INDICATOR MESHES
8 | //-------------------------------------------------------------------------
9 |
10 | MODEL
11 | {
12 | model = IndicatorLights/Meshes/squareLamp2
13 | scale = 0.7, 0.6, 2.83
14 | position = 0, 1.452, -0.0147
15 | }
16 |
17 | //-------------------------------------------------------------------------
18 | // CONTROLLABLE EMISSIVES
19 | //-------------------------------------------------------------------------
20 |
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/squareLamp2
24 | emissiveName = indicator
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLERS
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleOrbitalSurveyorIndicator
33 | emissiveName = indicator
34 | alreadyScannedColor = dim($ToggleLED, 0.65)
35 | potentialScanColor = blink(dim($ToggleLED, 0.8), 150, $Off, 1050)
36 | readyScanColor = blink($ToggleLED, 200, $Off, 200)
37 | unusableColor = blink($Warning, 200, $Off, 200)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/files/Patches/IndicatorLights_KIS.cfg:
--------------------------------------------------------------------------------
1 | // This is needed to let KIS know that the various PartModules that
2 | // IndicatorLights provides shouldn't disqualify parts from being
3 | // stackable in KIS containers.
4 | //
5 | // Thanks to Enceos in the KSP forums for pointing out the need
6 | // for this patch.
7 |
8 | @KISConfig[*]:NEEDS[KIS]
9 | {
10 | @StackableModule
11 | {
12 | moduleName = ModuleBiomeScannerIndicator
13 | moduleName = ModuleBooleanIndicator
14 | moduleName = ModuleControllableEmissive
15 | moduleName = ModuleConverterIndicator
16 | moduleName = ModuleCrewIndicator
17 | moduleName = ModuleCrewIndicatorToggle
18 | moduleName = ModuleCustomBlink
19 | moduleName = ModuleCustomColoredEmissive
20 | moduleName = ModuleDataTransmitterIndicator
21 | moduleName = ModuleDockingCrossfeedIndicator
22 | moduleName = ModuleDockingStateIndicator
23 | moduleName = ModuleEmissiveArrayController
24 | moduleName = ModuleIndicatorToggle
25 | moduleName = ModuleOrbitalSurveyorIndicator
26 | moduleName = ModuleReactionWheelIndicator
27 | moduleName = ModuleResourceEnabledIndicator
28 | moduleName = ModuleResourceLevelIndicator
29 | moduleName = ModuleResourceScannerIndicator
30 | moduleName = ModuleScalarIndicator
31 | moduleName = ModuleScienceAvailabilityIndicator
32 | moduleName = ModuleScienceContainerIndicator
33 | moduleName = ModuleScienceDataIndicator
34 | moduleName = ModuleToggleLED
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Console/HelpCommand.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace IndicatorLights.Console
4 | {
5 | ///
6 | /// Show all the various IndicatorLights console commands.
7 | ///
8 | internal class HelpCommand : DebugConsole.DebugConsoleCommand
9 | {
10 | public const string COMMAND = "help";
11 | private const string HELP = "Shows this message";
12 |
13 | public HelpCommand() : base(COMMAND, HELP) {}
14 |
15 | public override void Call(string[] arguments)
16 | {
17 | StringBuilder builder = new StringBuilder();
18 | builder.AppendFormat("Commands available via /{0}:", DebugConsole.COMMAND);
19 | for (int i = 0; i < DebugConsole.COMMANDS.Length; ++i)
20 | {
21 | builder.Append("\n").Append(HelpStringOf(DebugConsole.COMMANDS[i]));
22 | }
23 | Logging.Log(builder.ToString());
24 | }
25 |
26 | internal static string HelpStringOf(DebugConsole.DebugConsoleCommand command)
27 | {
28 | if (command.Usage == null)
29 | {
30 | return string.Format("/{0} {1}: {2}", DebugConsole.COMMAND, command.Command, command.Help);
31 | }
32 | else
33 | {
34 | return string.Format("/{0} {1} {2}: {3}", DebugConsole.COMMAND, command.Command, command.Usage, command.Help);
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("IndicatorLights")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyProduct("IndicatorLights")]
11 | [assembly: AssemblyCopyright("Copyright © Snark 2016")]
12 | [assembly: AssemblyTrademark("")]
13 | [assembly: AssemblyCulture("")]
14 |
15 | // Setting ComVisible to false makes the types in this assembly not visible
16 | // to COM components. If you need to access a type in this assembly from
17 | // COM, set the ComVisible attribute to true on that type.
18 | [assembly: ComVisible(false)]
19 |
20 | // The following GUID is for the ID of the typelib if this project is exposed to COM
21 | [assembly: Guid("8448de0d-400e-4f55-815e-fdf996f6bc4b")]
22 |
23 | // Version information for an assembly consists of the following four values:
24 | //
25 | // Major Version
26 | // Minor Version
27 | // Build Number
28 | // Revision
29 | //
30 | // You can specify all the values or you can default the Build and Revision Numbers
31 | // by using the '*' as shown below:
32 | // [assembly: AssemblyVersion("1.0.*")]
33 | [assembly: AssemblyVersion("1.0.0.0")]
34 | [assembly: AssemblyFileVersion("1.0.0.0")]
35 |
--------------------------------------------------------------------------------
/src/ModuleDockingCrossfeedIndicator.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Picks a solid color, based on crossfeed enabled/disabled status.
7 | ///
8 | public class ModuleDockingCrossfeedIndicator : ModuleSourceIndicator, IToggle
9 | {
10 | [KSPField]
11 | [ColorSourceIDField]
12 | public string crossfeedOnSource = Colors.ToString(DefaultColor.DockingCrossfeedOn);
13 |
14 | [KSPField]
15 | [ColorSourceIDField]
16 | public string crossfeedOffSource = Colors.ToString(DefaultColor.DockingCrossfeedOff);
17 |
18 | private IColorSource onSource = null;
19 | private IColorSource offSource = null;
20 |
21 | public override void ParseIDs()
22 | {
23 | base.ParseIDs();
24 | onSource = FindColorSource(crossfeedOnSource);
25 | offSource = FindColorSource(crossfeedOffSource);
26 | }
27 |
28 | public override Color OutputColor
29 | {
30 | get
31 | {
32 | if (SourceModule == null) return Color.black;
33 | return SourceModule.crossfeed ? onSource.OutputColor : offSource.OutputColor;
34 | }
35 | }
36 |
37 | ///
38 | /// IToggle implementation.
39 | ///
40 | public bool ToggleStatus
41 | {
42 | get
43 | {
44 | return (SourceModule == null)? false : SourceModule.crossfeed;
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/files/Parts/dockingPorts/inflatableAirlock.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the inflatable airlock.
2 | // When someone's in the airlock: it's a crew indicator.
3 | // When there's nobody in the airlock: it acts as a standard docking-port indicator.
4 |
5 | @PART[InflatableAirlock]:NEEDS[SquadExpansion]:FOR[IndicatorLights] {
6 |
7 | //-------------------------------------------------------------------------
8 | // INDICATOR MESHES
9 | //-------------------------------------------------------------------------
10 | MODEL
11 | {
12 | model = IndicatorLights/Meshes/squareLamp
13 | scale = 1, 0.25, 1
14 | position = 0, 0.165, -0.477
15 | rotation = 0, 180, 0
16 | }
17 |
18 |
19 | //-------------------------------------------------------------------------
20 | // CONTROLLABLE EMISSIVES
21 | //-------------------------------------------------------------------------
22 | MODULE {
23 | name = ModuleControllableEmissive
24 | target = IndicatorLights/Meshes/squareLamp
25 | emissiveName = indicator
26 | }
27 |
28 |
29 | //-------------------------------------------------------------------------
30 | // CONTROLLERS
31 | //-------------------------------------------------------------------------
32 | MODULE {
33 | name = ModuleDockingCrossfeedIndicator
34 | }
35 |
36 | MODULE {
37 | name = ModuleDockingStateIndicator
38 | readyColor = $Off
39 | acquireColor = blink(ModuleDockingCrossfeedIndicator, 100, $Off, 100)
40 | disengageColor = blink(ModuleDockingCrossfeedIndicator, 120, $Off, 1080)
41 | }
42 |
43 | MODULE {
44 | name = ModuleCrewIndicator
45 | emissiveName = indicator
46 | emptyColor = ModuleDockingStateIndicator
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/examples/VesselControlLevel.cfg:
--------------------------------------------------------------------------------
1 | // Demonstrate the use of controlLevel() syntax.
2 | //
3 | // This example adds a light to the HECS2 probe core, which lights up in
4 | // various vessel control levels (see comments below).
5 |
6 | @PART[HECS2_ProbeCore] {
7 |
8 | //-------------------------------------------------------------------------
9 | // INDICATOR MESHES
10 | //-------------------------------------------------------------------------
11 |
12 | MODEL
13 | {
14 | model = IndicatorLights/Meshes/nubbinLamp
15 | scale = 1.5, 1.5, 0.6
16 | position = 0, 0.02, -0.73
17 | rotation = 0, 180, 0
18 | }
19 |
20 |
21 | //-------------------------------------------------------------------------
22 | // CONTROLLABLE EMISSIVES
23 | //-------------------------------------------------------------------------
24 |
25 | // This emissive shows current control status of the vessel.
26 | MODULE {
27 | name = ModuleControllableEmissive
28 | target = IndicatorLights/Meshes/nubbinLamp
29 | emissiveName = controlLevelIndicator
30 | }
31 |
32 |
33 | //-------------------------------------------------------------------------
34 | // CONTROLLERS
35 | //-------------------------------------------------------------------------
36 |
37 | // This controls the control level indicator. Green when full control, yellow
38 | // when partial control (manned), red for partial control (unmanned), off for no control.
39 | MODULE {
40 | name = ModuleBooleanIndicator
41 | input = controlLevel(PARTIAL_UNMANNED, PARTIAL_MANNED, FULL)
42 | emissiveName = controlLevelIndicator
43 | activeColor = if(controlLevel(FULL), $ToggleLED, if(controlLevel(PARTIAL_MANNED), $MediumResource, $LowResource))
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/files/Parts/robotics/kal1000.cfg:
--------------------------------------------------------------------------------
1 | // Adds an LED indicator to the KAL-1000 robotic controller.
2 |
3 | @PART[controller1000]:NEEDS[SquadExpansion/Serenity]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status light!:
5 |
6 | // We have to re-specify the model for the stock part, because this part
7 | // uses the older "mesh =" syntax in its .cfg file instead of the newer
8 | // "MODEL" syntax. The "mesh =" syntax doesn't allow having multiple models
9 | // as part of the same part, which would prevent this mod from adding meshes
10 | // for the indicator lights.
11 | MODEL
12 | {
13 | model = SquadExpansion/Serenity/Parts/Robotics/Controllers/controller1000
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/nubbinLamp
22 | scale = 0.65, 0.65, 1
23 | position = 0.093147, 0.034181, -0.13876
24 | rotation = 180, 0, 0
25 | }
26 |
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLABLE EMISSIVES
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleControllableEmissive
34 | target = IndicatorLights/Meshes/nubbinLamp
35 | emissiveName = indicator
36 | }
37 |
38 | //-------------------------------------------------------------------------
39 | // CONTROLLERS
40 | //-------------------------------------------------------------------------
41 |
42 | MODULE {
43 | name = ModuleRoboticControllerIndicator
44 | emissiveName = indicator
45 | }
46 | }
--------------------------------------------------------------------------------
/files/Parts/science/scienceBox.cfg:
--------------------------------------------------------------------------------
1 | @PART[ScienceBox]:FOR[IndicatorLights]
2 | {
3 |
4 | //-------------------------------------------------------------------------
5 | // INDICATOR MESHES
6 | //-------------------------------------------------------------------------
7 | MODEL
8 | {
9 | model = IndicatorLights/Meshes/squareLamp
10 | scale = 0.3, 4, 0.5
11 | position = -0.2150, 0, -0.2150
12 | rotation = 0, 225, 0
13 | }
14 |
15 | MODEL
16 | {
17 | model = IndicatorLights/Meshes/squareLamp
18 | scale = 0.3, 4, 0.5
19 | position = 0.2150, 0, -0.2150
20 | rotation = 0, 135, 0
21 | }
22 |
23 | MODEL
24 | {
25 | model = IndicatorLights/Meshes/squareLamp
26 | scale = 0.3, 4, 0.5
27 | position = 0.2150, 0, 0.2150
28 | rotation = 0, 45, 0
29 | }
30 |
31 | MODEL
32 | {
33 | model = IndicatorLights/Meshes/squareLamp
34 | scale = 0.3, 4, 0.5
35 | position = -0.2150, 0, 0.2150
36 | rotation = 0, 315, 0
37 | }
38 |
39 |
40 | //-------------------------------------------------------------------------
41 | // CONTROLLABLE EMISSIVES
42 | //-------------------------------------------------------------------------
43 | MODULE {
44 | name = ModuleControllableEmissive
45 | target = IndicatorLights/Meshes/squareLamp
46 | emissiveName = indicator
47 | }
48 |
49 |
50 | //-------------------------------------------------------------------------
51 | // CONTROLLERS
52 | //-------------------------------------------------------------------------
53 |
54 | MODULE {
55 | name = ModuleScienceContainerIndicator
56 | emissiveName = indicator
57 | dataColor = $HighScience
58 | partialDataColor = $MediumScience
59 | lowDataColor = $LowScience
60 | emptyColor = $Off
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/files/Parts/science/gravioli.cfg:
--------------------------------------------------------------------------------
1 | @PART[sensorGravimeter]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this is
5 | // an older part that uses the "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/sensorGravimeter/model
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/squareLamp2
21 | scale = 1.16, 0.6, 1.16
22 | position = 0, 0.1053, -0.0862
23 | }
24 |
25 |
26 | //-------------------------------------------------------------------------
27 | // CONTROLLABLE EMISSIVES
28 | //-------------------------------------------------------------------------
29 | MODULE {
30 | name = ModuleControllableEmissive
31 | target = IndicatorLights/Meshes/squareLamp2
32 | emissiveName = indicator
33 | }
34 |
35 |
36 | //-------------------------------------------------------------------------
37 | // CONTROLLERS
38 | //-------------------------------------------------------------------------
39 |
40 | MODULE {
41 | name = ModuleScienceDataIndicator
42 | emissiveName = indicator
43 | dataColor = $HighScience
44 | partialDataColor = $MediumScience
45 | lowDataColor = $LowScience
46 | emptyColor = ModuleScienceAvailabilityIndicator
47 | }
48 |
49 | MODULE {
50 | name = ModuleScienceAvailabilityIndicator
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/RateLimiter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Utility class for enabling performing an action no more frequently than
7 | /// a specified time interval. (For example, if updating on every Unity frame
8 | /// would be too expensive, so you want to do it no more often than every
9 | /// N milliseconds.)
10 | ///
11 | internal class RateLimiter
12 | {
13 | private readonly TimeSpan interval;
14 | private DateTime nextUpdate;
15 |
16 | ///
17 | /// Constructor.
18 | ///
19 | ///
20 | public RateLimiter(TimeSpan interval)
21 | {
22 | this.interval = interval;
23 | this.nextUpdate = DateTime.MinValue;
24 | }
25 |
26 | ///
27 | /// Resets the limiter, i.e. forces the next call to Check() to return true.
28 | ///
29 | public void Reset()
30 | {
31 | nextUpdate = DateTime.MinValue;
32 | }
33 |
34 | ///
35 | /// Returns true if it's never been called before, or if the time since it
36 | /// last returned true is at least the specified interval. Otherwise, returns false.
37 | ///
38 | ///
39 | public bool Check()
40 | {
41 | DateTime now = DateTime.Now;
42 | if (now > nextUpdate)
43 | {
44 | nextUpdate = now + interval;
45 | return true;
46 | }
47 | else
48 | {
49 | return false;
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/files/Parts/crewable/mk1cockpit.cfg:
--------------------------------------------------------------------------------
1 | // Adds an occupancy indicator to the Mk1 cockpit.
2 |
3 | @PART[Mark1Cockpit]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp
12 | scale = 1, 0.25, 0.5
13 | position = -0.583, 0.035, 0.2126
14 | rotation = 0, -70, 0
15 | }
16 |
17 | //-------------------------------------------------------------------------
18 | // CONTROLLABLE EMISSIVES
19 | //-------------------------------------------------------------------------
20 |
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/squareLamp
24 | emissiveName = indicator
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLERS
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleCrewIndicatorToggle
33 | toggleName = indicatorToggle
34 | }
35 |
36 | MODULE {
37 | name = ModuleCrewIndicator
38 | toggleName = indicatorToggle
39 | }
40 |
41 | MODULE
42 | {
43 | name = ModuleScienceAvailabilityIndicator
44 | experimentID = crewReport
45 | lowValueColor = ModuleCrewIndicator
46 | mediumValueColor = highValueColor
47 | highValueColor = blink(lowValueColor, 200, $Off, 200)
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceDataIndicator
52 | experimentID = crewReport
53 | emissiveName = indicator
54 | dataColor = ModuleCrewIndicator
55 | emptyColor = ModuleScienceAvailabilityIndicator
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/files/Parts/science/barometer.cfg:
--------------------------------------------------------------------------------
1 | @PART[sensorBarometer]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this is
5 | // an older part that uses the "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/sensorBarometer/model
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/nubbinLamp
21 | scale = 0.5, 0.5, 0.5
22 | position = 0.02, 0, -0.0427
23 | rotation = 0, 0, 0
24 | }
25 |
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 | MODULE {
31 | name = ModuleControllableEmissive
32 | target = IndicatorLights/Meshes/nubbinLamp
33 | emissiveName = indicator
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleScienceDataIndicator
43 | emissiveName = indicator
44 | dataColor = $HighScience
45 | partialDataColor = $MediumScience
46 | lowDataColor = $LowScience
47 | emptyColor = ModuleScienceAvailabilityIndicator
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceAvailabilityIndicator
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/files/Parts/science/magnetometer.cfg:
--------------------------------------------------------------------------------
1 | @PART[Magnetometer]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this part
5 | // inexplicably uses the older "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/Magnetometer/Magnetometer
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/nubbinLamp
21 | scale = 4.6, 4.6, 3
22 | position = 0, 0.21325, 0
23 | rotation = 90, 0, 0
24 | }
25 |
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 | MODULE {
31 | name = ModuleControllableEmissive
32 | target = IndicatorLights/Meshes/nubbinLamp
33 | emissiveName = indicator
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleScienceDataIndicator
43 | emissiveName = indicator
44 | dataColor = $HighScience
45 | partialDataColor = $MediumScience
46 | lowDataColor = $LowScience
47 | emptyColor = ModuleScienceAvailabilityIndicator
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceAvailabilityIndicator
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/files/Parts/crewable/mk1cockpitInline.cfg:
--------------------------------------------------------------------------------
1 | // Adds an occupancy indicator to the Mk1 inline cockpit.
2 |
3 | @PART[Mark2Cockpit]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp
12 | scale = 0.25, 1.1, 0.5
13 | position = -0.419, 0.1, -0.501
14 | rotation = 0, -125, 0
15 | }
16 |
17 | //-------------------------------------------------------------------------
18 | // CONTROLLABLE EMISSIVES
19 | //-------------------------------------------------------------------------
20 |
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/squareLamp
24 | emissiveName = indicator
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLERS
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleCrewIndicatorToggle
33 | toggleName = indicatorToggle
34 | }
35 |
36 | MODULE {
37 | name = ModuleCrewIndicator
38 | toggleName = indicatorToggle
39 | }
40 |
41 | MODULE
42 | {
43 | name = ModuleScienceAvailabilityIndicator
44 | experimentID = crewReport
45 | lowValueColor = ModuleCrewIndicator
46 | mediumValueColor = highValueColor
47 | highValueColor = blink(lowValueColor, 200, $Off, 200)
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceDataIndicator
52 | experimentID = crewReport
53 | emissiveName = indicator
54 | dataColor = ModuleCrewIndicator
55 | emptyColor = ModuleScienceAvailabilityIndicator
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/files/Parts/science/variometer.cfg:
--------------------------------------------------------------------------------
1 | @PART[sensorAtmosphere]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this is
5 | // an older part that uses the "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/AtmosphereSensor/model
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/squareLamp
21 | scale = 0.3, 2, 0.3
22 | position = 0, 0.11416, -0.30133
23 | rotation = 0, 180, 0
24 | }
25 |
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 | MODULE {
31 | name = ModuleControllableEmissive
32 | target = IndicatorLights/Meshes/squareLamp
33 | emissiveName = indicator
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleScienceDataIndicator
43 | emissiveName = indicator
44 | dataColor = $HighScience
45 | partialDataColor = $MediumScience
46 | lowDataColor = $LowScience
47 | emptyColor = ModuleScienceAvailabilityIndicator
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceAvailabilityIndicator
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/files/Parts/science/thermometer.cfg:
--------------------------------------------------------------------------------
1 | @PART[sensorThermometer]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this is
5 | // an older part that uses the "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/sensorThermometer/model
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/squareLamp
21 | scale = 0.6, 0.3, 0.5
22 | position = 0, 0.11614, -0.05016
23 | rotation = 0, 180, 0
24 | }
25 |
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 | MODULE {
31 | name = ModuleControllableEmissive
32 | target = IndicatorLights/Meshes/squareLamp
33 | emissiveName = indicator
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleScienceDataIndicator
43 | emissiveName = indicator
44 | dataColor = $HighScience
45 | partialDataColor = $MediumScience
46 | lowDataColor = $LowScience
47 | emptyColor = ModuleScienceAvailabilityIndicator
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceAvailabilityIndicator
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/files/Parts/science/accelerometer.cfg:
--------------------------------------------------------------------------------
1 | @PART[sensorAccelerometer]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this is
5 | // an older part that uses the "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/sensorAccelerometer/model
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/nubbinLamp
21 | scale = 1, 1, 0.3
22 | position = 0, 0.11417, -0.08097
23 | rotation = -90, 0, 0
24 | }
25 |
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 | MODULE {
31 | name = ModuleControllableEmissive
32 | target = IndicatorLights/Meshes/nubbinLamp
33 | emissiveName = indicator
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleScienceDataIndicator
43 | emissiveName = indicator
44 | dataColor = $HighScience
45 | partialDataColor = $MediumScience
46 | lowDataColor = $LowScience
47 | emptyColor = ModuleScienceAvailabilityIndicator
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceAvailabilityIndicator
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/files/Parts/batteries/Z400Indicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the 400 EC battery.
2 |
3 | @PART[ksp_r_largeBatteryPack]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status light!:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Electrical/z-400Battery/model
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 |
20 | MODEL
21 | {
22 | model = IndicatorLights/Meshes/nubbinLamp
23 | position = 0, 0.292, -0.139
24 | rotation = -90, 0, 0
25 | }
26 |
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLABLE EMISSIVES
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleControllableEmissive
34 | target = IndicatorLights/Meshes/nubbinLamp
35 | emissiveName = indicator
36 | }
37 |
38 |
39 | //-------------------------------------------------------------------------
40 | // CONTROLLERS
41 | //-------------------------------------------------------------------------
42 |
43 | MODULE {
44 | name = ModuleResourceLevelIndicator
45 | }
46 |
47 | MODULE {
48 | name = ModuleResourceEnabledIndicator
49 | enabledColor = ModuleResourceLevelIndicator
50 | disabledColor = blink(ModuleResourceLevelIndicator, 900, $Off, 300)
51 | emissiveName = indicator
52 | }
53 | }
--------------------------------------------------------------------------------
/examples/AttachableResourceIndicator.cfg:
--------------------------------------------------------------------------------
1 | // Sample config to have a part that shows the resource level of its *parent* part.
2 | // We'll use ModuleManager to clone the BL-01 standalone indicator light and give
3 | // it new behavior.
4 | //
5 | // If you're wondering "hey, this is cool, why is this just an example, rather than
6 | // being an actual part?", it's because there's still a sizable chunk of work left
7 | // to do to make this into a polished, shippable product. First, there would need to
8 | // be some sort of UI available to pick which resource to show. Second, a real standalone
9 | // part really ought to have a model of its own, rather than being an exact visual copy
10 | // of the BL-01 light. Someday I may make something like this as an actual part for
11 | // IndicatorLights that gets installed by default, but for now it's just a sample.
12 | //
13 | +PART[indicatorLightSmall] {
14 | @name = attachableResourceIndicator
15 | @title = Attachable Resource Indicator
16 | @description = This prototype indicator can be attached anywhere. When attached to a resource-containing part, it shows the level of the resource. (If the part has multiple resources, it picks the first one.)
17 | @tags = snark indicator resource sample example
18 |
19 | // get rid of all the IndicatorLights modules on the parent part
20 | -MODULE[ModuleToggleLED] {}
21 | -MODULE[ModuleCustomColoredEmissive] {}
22 | -MODULE[ModuleCustomColoredEmissive] {}
23 | -MODULE[ModuleCustomBlink] {}
24 |
25 | // now add new ones
26 | MODULE {
27 | name = ModuleResourceLevelIndicator
28 | searchStrategy = parent
29 | }
30 |
31 | MODULE {
32 | name = ModuleResourceEnabledIndicator
33 | searchStrategy = parent
34 | enabledColor = ModuleResourceLevelIndicator
35 | disabledColor = blink(ModuleResourceLevelIndicator, 900, $Off, 300)
36 | emissiveName = light
37 | }
38 | }
--------------------------------------------------------------------------------
/files/Parts/batteries/Z100Indicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the 100 EC battery.
2 |
3 | @PART[batteryPack]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status light!:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Electrical/z-100Battery/model
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/z100lamp
22 | scale = 1.02, 1, 1.02
23 | position = 0.04252, 0.208, -0.08216 // inverted X, moved Y up a bit
24 | }
25 |
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleControllableEmissive
33 | target = IndicatorLights/Meshes/z100lamp
34 | emissiveName = indicator
35 | }
36 |
37 |
38 | //-------------------------------------------------------------------------
39 | // CONTROLLERS
40 | //-------------------------------------------------------------------------
41 |
42 | MODULE {
43 | name = ModuleResourceLevelIndicator
44 | }
45 |
46 | MODULE {
47 | name = ModuleResourceEnabledIndicator
48 | enabledColor = ModuleResourceLevelIndicator
49 | disabledColor = blink(ModuleResourceLevelIndicator, 900, $Off, 300)
50 | emissiveName = indicator
51 | }
52 | }
--------------------------------------------------------------------------------
/src/VesselScienceTracker.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 |
4 | namespace IndicatorLights
5 | {
6 | ///
7 | /// Utility class for tracking which science subjects are contained in vessels.
8 | ///
9 | [KSPAddon(KSPAddon.Startup.Flight, false)]
10 | public class VesselScienceTracker : VesselRegistrar
11 | {
12 | private static VesselScienceTracker instance = null;
13 |
14 | public void Start()
15 | {
16 | instance = this;
17 | }
18 |
19 | ///
20 | /// Gets the science contents information for the specified vessel, or null if not found.
21 | ///
22 | ///
23 | ///
24 | public static VesselScienceContents Get(Vessel vessel)
25 | {
26 | return (instance == null) ? null : instance[vessel];
27 | }
28 |
29 | ///
30 | /// Here when a vessel is added.
31 | ///
32 | ///
33 | ///
34 | protected override VesselScienceContents OnAddVessel(Vessel vessel)
35 | {
36 | return new VesselScienceContents(vessel);
37 | }
38 |
39 | ///
40 | /// Here when a vessel is modified.
41 | ///
42 | ///
43 | ///
44 | ///
45 | protected override VesselScienceContents OnModifyVessel(Vessel vessel, VesselScienceContents data)
46 | {
47 | return new VesselScienceContents(vessel);
48 | }
49 |
50 | private void OnVesselSituationChange(GameEvents.HostedFromToAction data)
51 | {
52 | throw new NotImplementedException();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/files/Parts/science/telescope.cfg:
--------------------------------------------------------------------------------
1 | @PART[InfraredTelescope]:FOR[IndicatorLights]
2 | {
3 | //-------------------------------------------------------------------------
4 | // INDICATOR MESHES
5 | //-------------------------------------------------------------------------
6 |
7 | // ring around the lens, indicates active/inactive
8 | MODEL
9 | {
10 | model = IndicatorLights/Meshes/nubbinLamp
11 | scale = 7, 7, 3
12 | position = 0, 0.96, -0.725
13 | rotation = 0, 180, 0
14 | }
15 |
16 | // small side lamp, shows science availability
17 | MODEL
18 | {
19 | model = IndicatorLights/Meshes/nubbinLamp
20 | scale = 1.5, 1.5, 1
21 | position = -.309, 0.804, -0.715
22 | rotation = 0, 180, 0
23 | }
24 |
25 |
26 | //-------------------------------------------------------------------------
27 | // CONTROLLABLE EMISSIVES
28 | //-------------------------------------------------------------------------
29 | MODULE {
30 | name = ModuleControllableEmissive
31 | target = IndicatorLights/Meshes/nubbinLamp:0
32 | emissiveName = activity
33 | }
34 |
35 | MODULE {
36 | name = ModuleControllableEmissive
37 | target = IndicatorLights/Meshes/nubbinLamp:1
38 | emissiveName = science
39 | }
40 |
41 |
42 | //-------------------------------------------------------------------------
43 | // CONTROLLERS
44 | //-------------------------------------------------------------------------
45 |
46 | MODULE {
47 | name = ModuleBooleanIndicator
48 | emissiveName = activity
49 | input = isTracking@SentinelModule
50 | activeColor = pulsate(random(#FF3000, #FF6000, 5000, 0.7), 2370, 0.5)
51 | inactiveColor = $Off
52 | }
53 |
54 | MODULE {
55 | name = ModuleScienceDataIndicator
56 | emissiveName = science
57 | dataColor = $HighScience
58 | partialDataColor = $MediumScience
59 | lowDataColor = $LowScience
60 | emptyColor = ModuleScienceAvailabilityIndicator
61 | }
62 |
63 | MODULE {
64 | name = ModuleScienceAvailabilityIndicator
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Console/LightsEnabledCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IndicatorLights.Console
4 | {
5 | class LightsEnabledCommand : DebugConsole.DebugConsoleCommand
6 | {
7 | private const string COMMAND = "enabled";
8 | private const string STATUS_ON = "on";
9 | private const string STATUS_OFF = "off";
10 | private const string HELP = "Global switch for all lights in the mod";
11 | private const string USAGE = "{" + STATUS_ON + " | " + STATUS_OFF + "}";
12 |
13 | public LightsEnabledCommand() : base(COMMAND, HELP, USAGE) {}
14 |
15 |
16 | public override void Call(string[] arguments)
17 | {
18 | if (arguments.Length != 1)
19 | {
20 | Logging.Log(HelpCommand.HelpStringOf(this));
21 | return;
22 | }
23 |
24 | switch (arguments[0])
25 | {
26 | case STATUS_ON:
27 | if (GlobalSettings.IsEnabled)
28 | {
29 | Logging.Log("IndicatorLights is already enabled.");
30 | }
31 | else
32 | {
33 | GlobalSettings.IsEnabled = true;
34 | Logging.Log("Enabled IndicatorLights.");
35 | }
36 | break;
37 | case STATUS_OFF:
38 | if (GlobalSettings.IsEnabled)
39 | {
40 | GlobalSettings.IsEnabled = false;
41 | Logging.Log("Disabled IndicatorLights.");
42 | }
43 | else
44 | {
45 | Logging.Log("IndicatorLights is already disabled.");
46 | }
47 | break;
48 | default:
49 | Logging.Log(HelpCommand.HelpStringOf(this));
50 | break;
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/files/Parts/batteries/Z200Indicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the 200 EC battery.
2 |
3 | @PART[batteryBankMini]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status lights!:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Electrical/z-200Battery/model
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 0.4, 0.4, 1
23 | position = 0, 0, 0.3125
24 | rotation = 0, 0, 0
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/squareLamp
30 | scale = 0.4, 0.4, 1
31 | position = 0, 0, -0.3125
32 | rotation = 0, 180, 0
33 | }
34 |
35 |
36 | //-------------------------------------------------------------------------
37 | // CONTROLLABLE EMISSIVES
38 | //-------------------------------------------------------------------------
39 |
40 | MODULE {
41 | name = ModuleControllableEmissive
42 | target = IndicatorLights/Meshes/squareLamp
43 | emissiveName = indicator
44 | }
45 |
46 |
47 | //-------------------------------------------------------------------------
48 | // CONTROLLERS
49 | //-------------------------------------------------------------------------
50 |
51 | MODULE {
52 | name = ModuleResourceLevelIndicator
53 | }
54 |
55 | MODULE {
56 | name = ModuleResourceEnabledIndicator
57 | enabledColor = ModuleResourceLevelIndicator
58 | disabledColor = blink(ModuleResourceLevelIndicator, 900, $Off, 300)
59 | emissiveName = indicator
60 | }
61 | }
--------------------------------------------------------------------------------
/src/ScienceValue.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Classifies science value as low/medium/high.
5 | ///
6 | static class ScienceValue
7 | {
8 | public enum Fraction
9 | {
10 | Low,
11 | Medium,
12 | High
13 | }
14 |
15 | public const float DEFAULT_LOW_SCIENCE_THRESHOLD = 0.15f;
16 | public const float DEFAULT_HIGH_SCIENCE_THRESHOLD = 0.7f;
17 |
18 | ///
19 | /// Gets the subject with the specified ID as a fraction category.
20 | ///
21 | ///
22 | ///
23 | ///
24 | ///
25 | public static Fraction Get(string subjectID, float lowThreshold, float highThreshold)
26 | {
27 | return FractionOf(Get(subjectID), lowThreshold, highThreshold);
28 | }
29 |
30 | ///
31 | /// Gets the subject with the specified ID as a floating-point fraction.
32 | ///
33 | ///
34 | ///
35 | public static float Get(string subjectID)
36 | {
37 | if (ResearchAndDevelopment.Instance == null) return 1; // it's a sandbox game
38 | ScienceSubject subject = ResearchAndDevelopment.GetSubjectByID(subjectID);
39 | // subject will be null if we've never retrieved this science result before
40 | return (subject == null) ? 1 : ResearchAndDevelopment.GetSubjectValue(subject.science, subject);
41 | }
42 |
43 | public static Fraction FractionOf(float fraction, float lowThreshold, float highThreshold)
44 | {
45 | if (fraction >= highThreshold) return Fraction.High;
46 | if (fraction < lowThreshold) return Fraction.Low;
47 | return Fraction.Medium;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/files/Parts/reactionWheels/smallReactionWheel.cfg:
--------------------------------------------------------------------------------
1 | // Adds status indicators to the small 0.625m reaction wheel.
2 |
3 | @PART[sasModule]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 Indicator lights show the reaction wheel's status.:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Command/inlineReactionWheel/model
14 | }
15 |
16 |
17 | //-------------------------------------------------------------------------
18 | // INDICATOR MESHES
19 | //-------------------------------------------------------------------------
20 |
21 | // The lights we add have to be double the scale & position of what we'd
22 | // normally want, because this part has a rescaleFactor of 0.5 applied to
23 | // it for legacy reasons.
24 |
25 | MODEL
26 | {
27 | model = IndicatorLights/Meshes/squareLamp
28 | scale = 0.8, 0.8, 1
29 | position = 0, 0, 0.625
30 | rotation = 0, 0, 0
31 | }
32 |
33 | MODEL
34 | {
35 | model = IndicatorLights/Meshes/squareLamp
36 | scale = 0.8, 0.8, 1
37 | position = 0, 0, -0.625
38 | rotation = 0, 180, 0
39 | }
40 |
41 |
42 | //-------------------------------------------------------------------------
43 | // CONTROLLABLE EMISSIVES
44 | //-------------------------------------------------------------------------
45 |
46 | MODULE {
47 | name = ModuleControllableEmissive
48 | target = IndicatorLights/Meshes/squareLamp
49 | emissiveName = indicator
50 | }
51 |
52 |
53 | //-------------------------------------------------------------------------
54 | // CONTROLLERS
55 | //-------------------------------------------------------------------------
56 |
57 | MODULE {
58 | name = ModuleReactionWheelIndicator
59 | emissiveName = indicator
60 | }
61 | }
--------------------------------------------------------------------------------
/files/Parts/science/goo.cfg:
--------------------------------------------------------------------------------
1 | @PART[GooExperiment]:FOR[IndicatorLights]
2 | {
3 |
4 | // We have to re-specify the model for the stock part, because this is
5 | // an older part that uses the "mesh =" syntax in its .cfg file instead
6 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
7 | // multiple models as part of the same part, which would prevent this mod
8 | // from adding meshes for the indicator lights.
9 | MODEL
10 | {
11 | model = Squad/Parts/Science/GooExperiment/GooExperiment
12 | }
13 |
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/squareLamp
21 | scale = 0.5, 1.7, 0.5
22 | position = -0.2146, 0, -0.358
23 | rotation = 0, -90, 0
24 | }
25 |
26 | MODEL
27 | {
28 | model = IndicatorLights/Meshes/squareLamp
29 | scale = 0.5, 1.7, 0.5
30 | position = 0.2146, 0, -0.358
31 | rotation = 0, 90, 0
32 | }
33 |
34 | //-------------------------------------------------------------------------
35 | // CONTROLLABLE EMISSIVES
36 | //-------------------------------------------------------------------------
37 | MODULE {
38 | name = ModuleControllableEmissive
39 | target = IndicatorLights/Meshes/squareLamp
40 | emissiveName = indicator
41 | }
42 |
43 |
44 | //-------------------------------------------------------------------------
45 | // CONTROLLERS
46 | //-------------------------------------------------------------------------
47 |
48 | MODULE {
49 | name = ModuleScienceDataIndicator
50 | emissiveName = indicator
51 | dataColor = $HighScience
52 | partialDataColor = $MediumScience
53 | lowDataColor = $LowScience
54 | emptyColor = ModuleScienceAvailabilityIndicator
55 | lowScienceThreshold = 0.25
56 | highScienceThreshold = 0.8
57 | }
58 |
59 | MODULE {
60 | name = ModuleScienceAvailabilityIndicator
61 | lowScienceThreshold = 0.25
62 | highScienceThreshold = 0.8
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/ModuleEmissiveArrayController.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// A simple array controller that sets all meshes to the same basic pattern.
5 | /// Allows for an optional master toggle switch for picking which pattern is
6 | /// shown.
7 | ///
8 | [ExperimentalController]
9 | class ModuleEmissiveArrayController : ModuleEmissiveControllerBase
10 | {
11 | [KSPField]
12 | [ToggleIDField]
13 | public string toggleID = string.Empty;
14 |
15 | [KSPField]
16 | public string activeColor = string.Empty;
17 |
18 | [KSPField]
19 | public string inactiveColor = string.Empty;
20 |
21 | private IToggle toggle = null;
22 | private ColorSourceArray activeSource = null;
23 | private ColorSourceArray inactiveSource = null;
24 |
25 | public override void OnStart(StartState state)
26 | {
27 | base.OnStart(state);
28 | toggle = Identifiers.FindFirst(part, toggleID);
29 | activeSource = ColorSourceArray.of(activeColor);
30 | if (toggle == null)
31 | {
32 | if (!string.IsNullOrEmpty(inactiveColor))
33 | {
34 | Logging.Warn("Ignoring inactiveColor on " + GetType() + " of " + part.GetTitle() + " (no toggle was specified)");
35 | }
36 | }
37 | else
38 | {
39 | inactiveSource = ColorSourceArray.of(inactiveColor);
40 | }
41 | }
42 |
43 | ///
44 | /// Called on every frame when it's time to set colors on the controllable emissives.
45 | ///
46 | protected override void SetColors()
47 | {
48 | if ((toggle == null) || toggle.ToggleStatus)
49 | {
50 | activeSource.SetColors(this);
51 | }
52 | else
53 | {
54 | inactiveSource.SetColors(this);
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/files/Parts/scanners/surfaceScanner.cfg:
--------------------------------------------------------------------------------
1 | // Adds an LED indicator to the surface scanner unit.
2 |
3 | @PART[SurfaceScanner]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 LED indicates operational status.:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Resources/SurfaceScanner/SurfaceScanner
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 |
20 | MODEL
21 | {
22 | model = IndicatorLights/Meshes/squareLamp
23 | scale = 1, 0.5, 0.5
24 | position = 0, 0.047, -0.229
25 | rotation = 0, 180, 0
26 | }
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLABLE EMISSIVES
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleControllableEmissive
34 | target = IndicatorLights/Meshes/squareLamp
35 | emissiveName = indicator
36 | }
37 |
38 | //-------------------------------------------------------------------------
39 | // CONTROLLERS
40 | //-------------------------------------------------------------------------
41 |
42 | // Pick a color based on resource abundance, and whether we've unlocked
43 | // the current biome.
44 | MODULE {
45 | name = ModuleResourceScannerIndicator
46 | }
47 |
48 | // Then, if we're in a situation where we can do a biome scan, override
49 | // that with a "hey, you should do a scan now!" indication.
50 | MODULE {
51 | name = ModuleBiomeScannerIndicator
52 | emissiveName = indicator
53 | inactiveColor = ModuleResourceScannerIndicator
54 | readyColor = blink($ToggleLED, 200, $Off, 200)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Console/PartsCommand.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text;
3 |
4 | namespace IndicatorLights.Console
5 | {
6 | class PartsCommand : DebugConsole.DebugConsoleCommand
7 | {
8 | private const string COMMAND = "parts";
9 | private const string HELP = "List all IndicatorLights parts on the current vessel";
10 |
11 | public PartsCommand() : base(COMMAND, HELP) {}
12 |
13 | public override void Call(string[] arguments)
14 | {
15 | List parts = GetIndicatorLightsParts(this);
16 | if (parts.Count == 0)
17 | {
18 | Logging.Log("No IndicatorLights parts are present on this vessel.");
19 | return;
20 | }
21 | StringBuilder builder = new StringBuilder();
22 | builder.AppendFormat("{0} IndicatorLights parts found:", parts.Count);
23 | for (int i = 0; i < parts.Count; ++i)
24 | {
25 | builder.AppendFormat("\n{0}: {1}", i, Logging.GetTitle(parts[i]));
26 | }
27 | Logging.Log(builder.ToString());
28 | }
29 |
30 | internal static List GetIndicatorLightsParts(DebugConsole.DebugConsoleCommand command)
31 | {
32 | List allParts = command.GetVesselParts();
33 | List filteredParts = new List();
34 | for (int i = 0; i < allParts.Count; ++i)
35 | {
36 | Part part = allParts[i];
37 | if (IsIndicatorLightsPart(part))
38 | {
39 | filteredParts.Add(part);
40 | }
41 | }
42 | return filteredParts;
43 | }
44 |
45 | internal static bool IsIndicatorLightsPart(Part part)
46 | {
47 | for (int i = 0; i < part.Modules.Count; ++i)
48 | {
49 | PartModule module = part.Modules[i];
50 | if (module is ModuleControllableEmissive) return true;
51 | if (module is ModuleEmissiveController) return true;
52 | }
53 | return false;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/files/Parts/reactionWheels/largeReactionWheel.cfg:
--------------------------------------------------------------------------------
1 | // Adds status indicators to the large 2.5m reaction wheel.
2 |
3 | @PART[asasmodule1-2]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 Indicator lights show the reaction wheel's status.:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Command/advancedSasModuleLarge/model
14 | }
15 |
16 |
17 | //-------------------------------------------------------------------------
18 | // INDICATOR MESHES
19 | //-------------------------------------------------------------------------
20 |
21 | MODEL
22 | {
23 | model = IndicatorLights/Meshes/squareLamp
24 | scale = 0.8, 0.8, 1
25 | position = -0.884, 0, 0.884
26 | rotation = 0, -45, 0
27 | }
28 |
29 | MODEL
30 | {
31 | model = IndicatorLights/Meshes/squareLamp
32 | scale = 0.8, 0.8, 1
33 | position = 0.884, 0, -0.884
34 | rotation = 0, 135, 0
35 | }
36 |
37 | MODEL
38 | {
39 | model = IndicatorLights/Meshes/squareLamp
40 | scale = 0.8, 0.8, 1
41 | position = 0.884, 0, 0.884
42 | rotation = 0, 45, 0
43 | }
44 |
45 | MODEL
46 | {
47 | model = IndicatorLights/Meshes/squareLamp
48 | scale = 0.8, 0.8, 1
49 | position = -0.884, 0, -0.884
50 | rotation = 0, 225, 0
51 | }
52 |
53 |
54 | //-------------------------------------------------------------------------
55 | // CONTROLLABLE EMISSIVES
56 | //-------------------------------------------------------------------------
57 |
58 | MODULE {
59 | name = ModuleControllableEmissive
60 | target = IndicatorLights/Meshes/squareLamp
61 | emissiveName = indicator
62 | }
63 |
64 |
65 | //-------------------------------------------------------------------------
66 | // CONTROLLERS
67 | //-------------------------------------------------------------------------
68 |
69 | MODULE {
70 | name = ModuleReactionWheelIndicator
71 | emissiveName = indicator
72 | }
73 | }
--------------------------------------------------------------------------------
/files/Parts/reactionWheels/mediumReactionWheel.cfg:
--------------------------------------------------------------------------------
1 | // Adds status indicators to the medium 1.25m reaction wheel.
2 |
3 | @PART[advSasModule]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 Indicator lights show the reaction wheel's status.:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Command/inlineAdvancedStabilizer/model
14 | }
15 |
16 |
17 | //-------------------------------------------------------------------------
18 | // INDICATOR MESHES
19 | //-------------------------------------------------------------------------
20 |
21 | MODEL
22 | {
23 | model = IndicatorLights/Meshes/squareLamp
24 | scale = 0.5, 0.5, 1
25 | position = -0.442, 0, 0.442
26 | rotation = 0, -45, 0
27 | }
28 |
29 | MODEL
30 | {
31 | model = IndicatorLights/Meshes/squareLamp
32 | scale = 0.5, 0.5, 1
33 | position = 0.442, 0, -0.442
34 | rotation = 0, 135, 0
35 | }
36 |
37 | MODEL
38 | {
39 | model = IndicatorLights/Meshes/squareLamp
40 | scale = 0.5, 0.5, 1
41 | position = 0.442, 0, 0.442
42 | rotation = 0, 45, 0
43 | }
44 |
45 | MODEL
46 | {
47 | model = IndicatorLights/Meshes/squareLamp
48 | scale = 0.5, 0.5, 1
49 | position = -0.442, 0, -0.442
50 | rotation = 0, 215, 0
51 | }
52 |
53 |
54 | //-------------------------------------------------------------------------
55 | // CONTROLLABLE EMISSIVES
56 | //-------------------------------------------------------------------------
57 |
58 | MODULE {
59 | name = ModuleControllableEmissive
60 | target = IndicatorLights/Meshes/squareLamp
61 | emissiveName = indicator
62 | }
63 |
64 |
65 | //-------------------------------------------------------------------------
66 | // CONTROLLERS
67 | //-------------------------------------------------------------------------
68 |
69 | MODULE {
70 | name = ModuleReactionWheelIndicator
71 | emissiveName = indicator
72 | }
73 | }
--------------------------------------------------------------------------------
/src/ModuleResourceEnabledIndicator.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// A controller that sets the display based on whether a resource is enabled/disabled.
7 | ///
8 | class ModuleResourceEnabledIndicator : ModuleResourceIndicator, IToggle
9 | {
10 | private IColorSource enabledSource = null;
11 | private IColorSource disabledSource = null;
12 |
13 | ///
14 | /// The color to display when the resource is enabled.
15 | ///
16 | [KSPField]
17 | [ColorSourceIDField]
18 | public string enabledColor = Colors.ToString(DefaultColor.ToggleLED.Value());
19 |
20 | ///
21 | /// The color to display when the resource is disabled.
22 | ///
23 | [KSPField]
24 | [ColorSourceIDField]
25 | public string disabledColor = ColorSources.Blink(
26 | ColorSources.Constant(DefaultColor.ToggleLED),
27 | 900,
28 | ColorSources.Constant(DefaultColor.Off),
29 | 300).ColorSourceID;
30 |
31 | public override void ParseIDs()
32 | {
33 | base.ParseIDs();
34 | enabledSource = FindColorSource(enabledColor);
35 | disabledSource = FindColorSource(disabledColor);
36 | }
37 |
38 | public override bool HasColor
39 | {
40 | get
41 | {
42 | return base.HasColor && CurrentSource.HasColor;
43 | }
44 | }
45 |
46 | public override Color OutputColor
47 | {
48 | get { return CurrentSource.OutputColor; }
49 | }
50 |
51 | private IColorSource CurrentSource
52 | {
53 | get
54 | {
55 | return ToggleStatus ? enabledSource : disabledSource;
56 | }
57 | }
58 |
59 | ///
60 | /// IToggle implementation.
61 | ///
62 | public bool ToggleStatus
63 | {
64 | get
65 | {
66 | PartResource resource = Resource;
67 | return (resource != null) && resource.flowState;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/ModuleSourceIndicator.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Base class for modules indicator controllers that depend on some other
5 | /// PartModule (e.g. a stock one) for their color.
6 | ///
7 | public abstract class ModuleSourceIndicator : ModuleEmissiveController where T : PartModule
8 | {
9 | private T sourceModule = null;
10 |
11 | ///
12 | /// Called when the module is starting up.
13 | ///
14 | ///
15 | public override void OnStart(StartState state)
16 | {
17 | base.OnStart(state);
18 |
19 | sourceModule = ChooseSource();
20 | if (sourceModule == null)
21 | {
22 | Logging.Warn("No " + typeof(T).Name + " found for " + part.GetTitle());
23 | }
24 | }
25 |
26 | public override bool HasColor
27 | {
28 | get { return sourceModule != null; }
29 | }
30 |
31 | protected T SourceModule
32 | {
33 | get { return sourceModule; }
34 | }
35 |
36 | ///
37 | /// Choose the source module to use, or null if no suitable source module could be found.
38 | /// Subclasses can override to customize the choice. Default behavior is simply to pick
39 | /// the first one found.
40 | ///
41 | ///
42 | private T ChooseSource()
43 | {
44 | if (part == null) return null;
45 | for (int i = 0; i < part.Modules.Count; ++i)
46 | {
47 | T candidate = part.Modules[i] as T;
48 | if ((candidate != null) && IsSource(candidate)) return candidate;
49 | }
50 | return null;
51 | }
52 |
53 | ///
54 | /// Determine whether the specified module is usable as a source. Default implementation
55 | /// is to always return true, so the first one found will be chosen.
56 | ///
57 | ///
58 | ///
59 | protected virtual bool IsSource(T candidate)
60 | {
61 | return true;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/files/Parts/batteries/Z1KIndicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the 1000 EC battery.
2 |
3 | @PART[batteryBank]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status lights!:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Electrical/z-1kBattery/model
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 |
20 | MODEL
21 | {
22 | model = IndicatorLights/Meshes/squareLamp
23 | scale = 0.5, 0.5, 1
24 | position = -0.442, 0, 0.442
25 | rotation = 0, -45, 0
26 | }
27 |
28 | MODEL
29 | {
30 | model = IndicatorLights/Meshes/squareLamp
31 | scale = 0.5, 0.5, 1
32 | position = 0.442, 0, -0.442
33 | rotation = 0, 135, 0
34 | }
35 |
36 | MODEL
37 | {
38 | model = IndicatorLights/Meshes/squareLamp
39 | scale = 0.5, 0.5, 1
40 | position = 0.442, 0, 0.442
41 | rotation = 0, 45, 0
42 | }
43 |
44 | MODEL
45 | {
46 | model = IndicatorLights/Meshes/squareLamp
47 | scale = 0.5, 0.5, 1
48 | position = -0.442, 0, -0.442
49 | rotation = 0, 215, 0
50 | }
51 |
52 |
53 | //-------------------------------------------------------------------------
54 | // CONTROLLABLE EMISSIVES
55 | //-------------------------------------------------------------------------
56 |
57 | MODULE {
58 | name = ModuleControllableEmissive
59 | target = IndicatorLights/Meshes/squareLamp
60 | emissiveName = indicator
61 | }
62 |
63 |
64 | //-------------------------------------------------------------------------
65 | // CONTROLLERS
66 | //-------------------------------------------------------------------------
67 |
68 | MODULE {
69 | name = ModuleResourceLevelIndicator
70 | }
71 |
72 | MODULE {
73 | name = ModuleResourceEnabledIndicator
74 | enabledColor = ModuleResourceLevelIndicator
75 | disabledColor = blink(ModuleResourceLevelIndicator, 900, $Off, 300)
76 | emissiveName = indicator
77 | }
78 | }
--------------------------------------------------------------------------------
/src/RenderType.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// These are the valid values for the renderType property on ModuleControllableEmissive.
7 | ///
8 | public enum RenderType
9 | {
10 | ///
11 | /// Controls the emissive color of the mesh.
12 | ///
13 | emissive,
14 |
15 | ///
16 | /// Controls the tint color of the mesh.
17 | ///
18 | tint,
19 |
20 | ///
21 | /// Controls the "main" color of the mesh (e.g. the diffuse color, for many shaders).
22 | ///
23 | main
24 | }
25 |
26 | ///
27 | /// Extension methods for RenderType.
28 | ///
29 | internal static class RenderTypes
30 | {
31 | ///
32 | /// The render type to use for everything, unless specified otherwise.
33 | ///
34 | public const RenderType Default = RenderType.emissive;
35 |
36 | private static readonly int EMISSIVE_COLOR_ID = Shader.PropertyToID("_EmissiveColor");
37 | private static readonly int TINT_COLOR_ID = Shader.PropertyToID("_TintColor");
38 | private static readonly int MAIN_COLOR_ID = Shader.PropertyToID("_Color");
39 |
40 | ///
41 | /// Gets the Unity shader property ID for this render type.
42 | ///
43 | ///
44 | ///
45 | public static int GetShaderPropertyId(this RenderType renderType)
46 | {
47 | switch (renderType)
48 | {
49 | case RenderType.emissive:
50 | return EMISSIVE_COLOR_ID;
51 |
52 | case RenderType.tint:
53 | return TINT_COLOR_ID;
54 |
55 | case RenderType.main:
56 | return MAIN_COLOR_ID;
57 |
58 | default:
59 | // Should never happen-- this means there's a bug, i.e. a new RenderType was added
60 | // without updating here.
61 | Logging.Error("Unknown render type " + renderType + ", defaulting to " + Default);
62 | return EMISSIVE_COLOR_ID;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/ModuleDockingStateIndicator.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Controls color based on the docking state (docked, undocked, engaged, disengaging).
7 | ///
8 | class ModuleDockingStateIndicator : ModuleSourceIndicator, IToggle
9 | {
10 | private const string ACQUIRE = "Acquire";
11 | private const string DISENGAGE = "Disengage";
12 |
13 | [KSPField]
14 | [ColorSourceIDField]
15 | public string readyColor = string.Empty;
16 |
17 | [KSPField]
18 | [ColorSourceIDField]
19 | public string acquireColor = string.Empty;
20 |
21 | [KSPField]
22 | [ColorSourceIDField]
23 | public string disengageColor = string.Empty;
24 |
25 | private IColorSource ready = null;
26 | private IColorSource acquire = null;
27 | private IColorSource disengage = null;
28 |
29 |
30 | public override void ParseIDs()
31 | {
32 | base.ParseIDs();
33 | ready = FindColorSource(readyColor);
34 | acquire = FindColorSource(acquireColor);
35 | disengage = FindColorSource(disengageColor);
36 | }
37 |
38 | public override Color OutputColor
39 | {
40 | get
41 | {
42 | if (SourceModule == null) return ready.OutputColor;
43 | string state = SourceModule.state;
44 | if (string.IsNullOrEmpty(state)) return ready.OutputColor;
45 | if (state.StartsWith(ACQUIRE)) return acquire.OutputColor;
46 | if (state.StartsWith(DISENGAGE)) return disengage.OutputColor;
47 | return ready.OutputColor;
48 | }
49 | }
50 |
51 | ///
52 | /// IToggle implementation.
53 | ///
54 | public bool ToggleStatus
55 | {
56 | get
57 | {
58 | // Toggle is considered "on" when we're engaging or disengaging, off at all other times.
59 | if (SourceModule == null) return false;
60 | string state = SourceModule.state;
61 | return string.IsNullOrEmpty(state)
62 | || state.StartsWith(ACQUIRE)
63 | || state.StartsWith(DISENGAGE);
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/files/Parts/crewable/mk1pod_v2.cfg:
--------------------------------------------------------------------------------
1 | // Adds an occupancy indicator to the Mk1 V2 command pod.
2 |
3 | @PART[mk1pod_v2]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp
12 | scale = 1.15, 0.25, 0.5
13 | position = 0, 0.173, -0.433
14 | rotation = -160, 0, 0
15 | }
16 |
17 | //-------------------------------------------------------------------------
18 | // CONTROLLABLE EMISSIVES
19 | //-------------------------------------------------------------------------
20 |
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/squareLamp
24 | emissiveName = indicator
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLERS
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleCrewIndicatorToggle
33 | toggleName = indicatorToggle
34 | }
35 |
36 | MODULE {
37 | name = ModuleCrewIndicator
38 | toggleName = indicatorToggle
39 | }
40 |
41 | MODULE
42 | {
43 | name = ModuleScienceAvailabilityIndicator
44 | experimentID = crewReport
45 | lowValueColor = ModuleCrewIndicator
46 | mediumValueColor = highValueColor
47 | highValueColor = blink(lowValueColor, 200, $Off, 200)
48 | }
49 |
50 | MODULE {
51 | name = ModuleScienceDataIndicator
52 | experimentID = crewReport
53 | emissiveName = indicator
54 | dataColor = ModuleCrewIndicator
55 | emptyColor = ModuleScienceAvailabilityIndicator
56 | }
57 |
58 | //-------------------------------------------------------------------------
59 | // TWEAKS
60 | //-------------------------------------------------------------------------
61 |
62 | // This pod uses a ModuleColorChanger to handle its cabin lights, set up
63 | // so that by default it takes control of *all* emissives on the part.
64 | // Need to tell it not to tinker with the meshes that we're adding here;
65 | // otherwise, the crew indicator will just turn on and off with the cabin
66 | // lights instead of actually working as a crew indicator.
67 | @MODULE[ModuleColorChanger] {
68 | excludedRenderer = IndicatorLights/Meshes/squareLamp(Clone)
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/files/Parts/crewable/kv1pod.cfg:
--------------------------------------------------------------------------------
1 | // Adds occupancy indicators to the "Shallot" command pod.
2 |
3 | @PART[kv1Pod]:NEEDS[SquadExpansion]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/nubbinLamp
12 | scale = 0.7, 0.7, 0.5
13 | position = 0, 0.293, -0.87
14 | rotation = -172, 0, 0
15 | }
16 |
17 | //-------------------------------------------------------------------------
18 | // CONTROLLABLE EMISSIVES
19 | //-------------------------------------------------------------------------
20 |
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/nubbinLamp
24 | emissiveName = indicator0
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLERS
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleCrewIndicatorToggle
33 | toggleName = indicatorToggle
34 | }
35 |
36 | MODULE {
37 | name = ModuleCrewIndicator
38 | controllerName = crewController0
39 | toggleName = indicatorToggle
40 | }
41 |
42 | MODULE
43 | {
44 | name = ModuleScienceAvailabilityIndicator
45 | controllerName = availability0
46 | experimentID = crewReport
47 | lowValueColor = crewController0
48 | mediumValueColor = highValueColor
49 | highValueColor = blink(lowValueColor, 200, $Off, 200)
50 | }
51 |
52 | MODULE {
53 | name = ModuleScienceDataIndicator
54 | experimentID = crewReport
55 | emissiveName = indicator0
56 | dataColor = crewController0
57 | emptyColor = availability0
58 | }
59 |
60 |
61 | //-------------------------------------------------------------------------
62 | // TWEAKS
63 | //-------------------------------------------------------------------------
64 |
65 | // This pod uses a ModuleColorChanger to handle its ablator, set up
66 | // so that by default it takes control of *all* emissives on the part.
67 | // Need to tell it not to tinker with the meshes that we're adding here;
68 | // otherwise, the crew indicator will end up getting colored with the
69 | // ablator instead of actually working as a crew indicator.
70 | @MODULE[ModuleColorChanger] {
71 | excludedRenderer = IndicatorLights/Meshes/nubbinLamp(Clone)
72 | }
73 | }
--------------------------------------------------------------------------------
/src/ModuleBiomeScannerIndicator.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Indicates whether the current biome can be surface-scanned or not.
7 | ///
8 | class ModuleBiomeScannerIndicator : ModuleSourceIndicator, IToggle
9 | {
10 | private IColorSource readySource;
11 | private IColorSource inactiveSource;
12 |
13 | ///
14 | /// The color to display when it's ready to take a biome scan.
15 | ///
16 | [KSPField]
17 | [ColorSourceIDField]
18 | public string readyColor = string.Empty;
19 |
20 | ///
21 | /// The color to display when it's inactive (either this biome has already been
22 | /// scanned, or else it's not in a usable situation).
23 | ///
24 | [KSPField]
25 | [ColorSourceIDField]
26 | public string inactiveColor = Colors.ToString(DefaultColor.Off);
27 |
28 | public override void ParseIDs()
29 | {
30 | base.ParseIDs();
31 | readySource = FindColorSource(readyColor);
32 | inactiveSource = FindColorSource(inactiveColor);
33 | }
34 |
35 | public override bool HasColor
36 | {
37 | get
38 | {
39 | return CurrentSource.HasColor;
40 | }
41 | }
42 |
43 | public override Color OutputColor
44 | {
45 | get
46 | {
47 | return CurrentSource.OutputColor;
48 | }
49 | }
50 |
51 | private IColorSource CurrentSource
52 | {
53 | get
54 | {
55 | return ToggleStatus ? readySource : inactiveSource;
56 | }
57 | }
58 |
59 | ///
60 | /// IToggle implementation.
61 | ///
62 | public bool ToggleStatus
63 | {
64 | get
65 | {
66 | // If we're in the editor, or not landed, then it's inactive.
67 | if (!HighLogic.LoadedSceneIsFlight
68 | || (vessel == null)
69 | || !vessel.LandedOrSplashed)
70 | return false;
71 |
72 | // Figure out what biome we're in
73 | string biomeName = vessel.GetCurrentBiome() ?? vessel.situation.ToString();
74 | return !ResourceMap.Instance.IsBiomeUnlocked(vessel.mainBody.flightGlobalsIndex, biomeName);
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Logging.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace IndicatorLights
5 | {
6 | ///
7 | /// Utility wrapper for logging messages.
8 | ///
9 | static class Logging
10 | {
11 | public static void Log(object message)
12 | {
13 | Debug.Log("[IndicatorLights] " + message);
14 | }
15 |
16 | public static void Warn(object message)
17 | {
18 | Debug.LogWarning("[IndicatorLights] " + message);
19 | }
20 |
21 | public static void Error(object message)
22 | {
23 | Debug.LogError("[IndicatorLights] " + message);
24 | }
25 |
26 | public static void Exception(string message, Exception e)
27 | {
28 | Error(message + " (" + e.GetType().Name + ") " + e.Message + ": " + e.StackTrace);
29 | }
30 |
31 | public static void Exception(Exception e)
32 | {
33 | Error("(" + e.GetType().Name + ") " + e.Message + ": " + e.StackTrace);
34 | }
35 |
36 | public static string GetTitle(this Part part)
37 | {
38 | return (part == null) ? "" : ((part.partInfo == null) ? part.partName : part.partInfo.title);
39 | }
40 |
41 | public static string GetIdentifier(object obj)
42 | {
43 | Identifiers.IIdentifiable identifiable = obj as Identifiers.IIdentifiable;
44 | return (identifiable == null) ? obj.GetType().Name : identifiable.Identifier;
45 | }
46 |
47 | ///
48 | /// Useful for debugging per-update-frame events without spamming the log to uselessness.
49 | ///
50 | public class Throttled
51 | {
52 | private readonly string label;
53 | private readonly RateLimiter cooldown;
54 |
55 | public Throttled(string label, long milliseconds)
56 | {
57 | this.label = label;
58 | this.cooldown = new RateLimiter(TimeSpan.FromMilliseconds(milliseconds));
59 | }
60 |
61 | public bool Log(object message)
62 | {
63 | DateTime now = DateTime.Now;
64 | if (!cooldown.Check()) return false;
65 | if (string.IsNullOrEmpty(label))
66 | {
67 | Logging.Log(message);
68 | }
69 | else
70 | {
71 | Logging.Log(label + ": " + message);
72 | }
73 | return true;
74 | }
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/files/Parts/indicatorLightSmall/indicatorLightSmall.cfg:
--------------------------------------------------------------------------------
1 | PART
2 | {
3 | name = indicatorLightSmall
4 | module = Part
5 | author = Snark
6 | mesh = model.mu
7 | rescaleFactor = 1
8 | node_attach = 0.0, 0.0, 0.0, 0.0, -1.0, 0.0
9 | TechRequired = engineering101
10 | entryCost = 500
11 | cost = 50
12 | category = Utility
13 | title = BL-01 Indicator Light
14 | manufacturer = Blinkenlights LLC
15 | description = Doesn't seem to achieve much, but we'll probably find out what it's for later on.
16 | attachRules = 0,1,0,0,1
17 | mass = 0.001
18 | dragModelType = default
19 | maximum_drag = 0.2
20 | minimum_drag = 0.2
21 | angularDrag = 1
22 | crashTolerance = 8
23 | maxTemp = 2400
24 | PhysicsSignificance = 1
25 | bulkheadProfiles = srf
26 | tags = snark indicator light blinken led
27 |
28 | MODULE {
29 | name = ModuleControllableEmissive
30 |
31 | // this identifies the mesh in the model that we're controlling
32 | target = light
33 |
34 | // this is the ID that ModuleToggleLED uses to find this
35 | emissiveName = light
36 | }
37 |
38 | // The main controller (identifiable as such because it specifies an
39 | // emissiveName, meaning that it's actually controlling something.
40 | //
41 | // Order is important. This module appears before the ModuleCustomColoredEmissive
42 | // modules before, because we want this module's UI to be above theirs in the
43 | // KSP vehicle editor.
44 | MODULE {
45 | name = ModuleToggleLED
46 |
47 | // the light is initially turned off
48 | status = false
49 |
50 | // this is the ModuleControllableEmissive we want to control
51 | emissiveName = light
52 |
53 | // this is where we get the color to show when the toggle is "on"
54 | activeColor = ModuleCustomBlink
55 |
56 | // this is where we get the color to show when the toggle is "off"
57 | inactiveColor = inactiveColorSource
58 |
59 | // make it operate with the Light action group by default
60 | defaultActionGroup = Light
61 | }
62 |
63 | MODULE {
64 | name = ModuleCustomColoredEmissive
65 |
66 | // This is the ID that ModuleCustomBlink uses to find this
67 | controllerName = activeColorSource
68 |
69 | label = On
70 | color = $ToggleLED
71 |
72 | // UI is initially turned off, since the light is initially turned on
73 | isUiEnabled = false
74 | }
75 |
76 | MODULE {
77 | name = ModuleCustomColoredEmissive
78 |
79 | // This is the ID that ModuleToggleLED and ModuleCustomBlink use to find this
80 | controllerName = inactiveColorSource
81 |
82 | label = Off
83 | color = $Off
84 | }
85 |
86 | MODULE {
87 | name = ModuleCustomBlink
88 | uiToggle = Editor
89 | onColor = activeColorSource
90 | offColor = inactiveColorSource
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/examples/RandomLights.cfg:
--------------------------------------------------------------------------------
1 | // Example of using the "random" color syntax. Adds three lights to
2 | // the Mk1 structural fuselage which, when turned on, blink in random
3 | // patterns.
4 | @PART[Mk1FuselageStructural] {
5 | @description ^= :(.)$:$0 With random lights!:
6 |
7 | //-------------------------------------------------------------------------
8 | // INDICATOR MESHES
9 | //-------------------------------------------------------------------------
10 |
11 | MODEL
12 | {
13 | model = IndicatorLights/Meshes/squareLamp
14 | scale = 1, 0.5, 1
15 | position = 0, 0.3, -0.625
16 | rotation = 0, 180, 0
17 | }
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 1, 0.5, 1
23 | position = 0, 0, -0.625
24 | rotation = 0, 180, 0
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/squareLamp
30 | scale = 1, 0.5, 1
31 | position = 0, -0.3, -0.625
32 | rotation = 0, 180, 0
33 | }
34 |
35 |
36 | //-------------------------------------------------------------------------
37 | // CONTROLLABLE EMISSIVES
38 | //-------------------------------------------------------------------------
39 |
40 | MODULE {
41 | name = ModuleControllableEmissive
42 | target = IndicatorLights/Meshes/squareLamp:0
43 | emissiveName = indicator1
44 | }
45 |
46 | MODULE {
47 | name = ModuleControllableEmissive
48 | target = IndicatorLights/Meshes/squareLamp:1
49 | emissiveName = indicator2
50 | }
51 |
52 | MODULE {
53 | name = ModuleControllableEmissive
54 | target = IndicatorLights/Meshes/squareLamp:2
55 | emissiveName = indicator3
56 | }
57 |
58 |
59 | //-------------------------------------------------------------------------
60 | // CONTROLLERS
61 | //-------------------------------------------------------------------------
62 |
63 | // This turns everybody on and off.
64 | MODULE {
65 | name = ModuleToggleLED
66 | }
67 |
68 | MODULE {
69 | name = ModuleBooleanIndicator
70 | input = ModuleToggleLED
71 | // Bias of +0.6 means it's on most of the time.
72 | activeColor = random($ToggleLED, $Off, 50, 0.6)
73 | inactiveColor = $Off
74 | emissiveName = indicator1
75 | }
76 |
77 | MODULE {
78 | name = ModuleBooleanIndicator
79 | input = ModuleToggleLED
80 | // Fun with compound color sources! :-)
81 | activeColor = random(random($ToggleLED, $Off, 50, 0.6), random(#FF0000, $Off, 50, -0.3), 300)
82 | inactiveColor = $Off
83 | emissiveName = indicator2
84 | }
85 |
86 | MODULE {
87 | name = ModuleBooleanIndicator
88 | input = ModuleToggleLED
89 | // Bias of -0.5 means it's off most of the time.
90 | activeColor = random($ToggleLED, $Off, 50, -0.5)
91 | inactiveColor = $Off
92 | emissiveName = indicator3
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/files/Parts/antennas/hg55.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the HG-55 antenna.
2 |
3 | @PART[HighGainAntenna]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp2
12 | position = 0, 0.080, 0.144
13 | scale = 2.5, 1, 0.8
14 | }
15 |
16 |
17 | //-------------------------------------------------------------------------
18 | // CONTROLLABLE EMISSIVES
19 | //-------------------------------------------------------------------------
20 |
21 | MODULE {
22 | name = ModuleControllableEmissive
23 | target = IndicatorLights/Meshes/squareLamp2
24 | emissiveName = indicator
25 | }
26 |
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLERS
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleDataTransmitterIndicator
34 | emissiveName = indicator
35 | // Get really fancy with busy color. This module type exposes one static
36 | // field, dataRate. We'll use a random flicker for the animation (like
37 | // an old-time modem), and we'll plug the data rate both into the flicker
38 | // period (so higher-speed antennas flicker faster), and into the bias
39 | // (so higher-speed antennas spend a greater percentage of their time
40 | // in the "on" state rather than "off").
41 | //
42 | // We don't actually have to use the static syntax here (we could just
43 | // take the data rate for this antenna, do the math, and plug in the
44 | // literal numbers here). However, using the actual static expression
45 | // comes with a few benefits. First, it's more maintainable: we
46 | // can just use the same static expression for all the antennas, rather
47 | // than having to come up with a different expression with different math
48 | // for each one. Second, it's more explicit to anyone reading this just
49 | // *why* the number is what it is. Third, it's more robust: if Squad ever
50 | // tinkers with the data rates, or someone uses ModuleManager to tweak
51 | // them, this will automatically follow suit. Fourth, it's friendlier
52 | // to modders: if you have your own antenna and you want to set it up
53 | // for IndicatorLights compatibility, you can just copy the following
54 | // line verbatim and you'll get behavior that's consistent with what
55 | // IndicatorLights does with the stock antennas.
56 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
57 | }
58 | }
--------------------------------------------------------------------------------
/files/Parts/antennas/smallRelayDish.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the small relay dish.
2 |
3 | @PART[RelayAntenna5]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/nubbinLamp
12 | position = 0, 0.389, 0
13 | scale = 2.2, 2.2, 1
14 | rotation = -90, 0, 0
15 | }
16 |
17 |
18 | //-------------------------------------------------------------------------
19 | // CONTROLLABLE EMISSIVES
20 | //-------------------------------------------------------------------------
21 |
22 | MODULE {
23 | name = ModuleControllableEmissive
24 | target = IndicatorLights/Meshes/nubbinLamp
25 | emissiveName = indicator
26 | }
27 |
28 |
29 | //-------------------------------------------------------------------------
30 | // CONTROLLERS
31 | //-------------------------------------------------------------------------
32 |
33 | MODULE {
34 | name = ModuleDataTransmitterIndicator
35 | emissiveName = indicator
36 | // Get really fancy with busy color. This module type exposes one static
37 | // field, dataRate. We'll use a random flicker for the animation (like
38 | // an old-time modem), and we'll plug the data rate both into the flicker
39 | // period (so higher-speed antennas flicker faster), and into the bias
40 | // (so higher-speed antennas spend a greater percentage of their time
41 | // in the "on" state rather than "off").
42 | //
43 | // We don't actually have to use the static syntax here (we could just
44 | // take the data rate for this antenna, do the math, and plug in the
45 | // literal numbers here). However, using the actual static expression
46 | // comes with a few benefits. First, it's more maintainable: we
47 | // can just use the same static expression for all the antennas, rather
48 | // than having to come up with a different expression with different math
49 | // for each one. Second, it's more explicit to anyone reading this just
50 | // *why* the number is what it is. Third, it's more robust: if Squad ever
51 | // tinkers with the data rates, or someone uses ModuleManager to tweak
52 | // them, this will automatically follow suit. Fourth, it's friendlier
53 | // to modders: if you have your own antenna and you want to set it up
54 | // for IndicatorLights compatibility, you can just copy the following
55 | // line verbatim and you'll get behavior that's consistent with what
56 | // IndicatorLights does with the stock antennas.
57 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
58 | }
59 | }
--------------------------------------------------------------------------------
/files/Parts/antennas/mediumRelayDish.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the medium relay dish.
2 |
3 | @PART[RelayAntenna50]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/nubbinLamp
12 | position = 0, 1.079, 0
13 | scale = 5, 5, 1.5
14 | rotation = -90, 0, 0
15 | }
16 |
17 |
18 | //-------------------------------------------------------------------------
19 | // CONTROLLABLE EMISSIVES
20 | //-------------------------------------------------------------------------
21 |
22 | MODULE {
23 | name = ModuleControllableEmissive
24 | target = IndicatorLights/Meshes/nubbinLamp
25 | emissiveName = indicator
26 | }
27 |
28 |
29 | //-------------------------------------------------------------------------
30 | // CONTROLLERS
31 | //-------------------------------------------------------------------------
32 |
33 | MODULE {
34 | name = ModuleDataTransmitterIndicator
35 | emissiveName = indicator
36 | // Get really fancy with busy color. This module type exposes one static
37 | // field, dataRate. We'll use a random flicker for the animation (like
38 | // an old-time modem), and we'll plug the data rate both into the flicker
39 | // period (so higher-speed antennas flicker faster), and into the bias
40 | // (so higher-speed antennas spend a greater percentage of their time
41 | // in the "on" state rather than "off").
42 | //
43 | // We don't actually have to use the static syntax here (we could just
44 | // take the data rate for this antenna, do the math, and plug in the
45 | // literal numbers here). However, using the actual static expression
46 | // comes with a few benefits. First, it's more maintainable: we
47 | // can just use the same static expression for all the antennas, rather
48 | // than having to come up with a different expression with different math
49 | // for each one. Second, it's more explicit to anyone reading this just
50 | // *why* the number is what it is. Third, it's more robust: if Squad ever
51 | // tinkers with the data rates, or someone uses ModuleManager to tweak
52 | // them, this will automatically follow suit. Fourth, it's friendlier
53 | // to modders: if you have your own antenna and you want to set it up
54 | // for IndicatorLights compatibility, you can just copy the following
55 | // line verbatim and you'll get behavior that's consistent with what
56 | // IndicatorLights does with the stock antennas.
57 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
58 | }
59 | }
--------------------------------------------------------------------------------
/src/PartSearchStrategy.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Determines how IndicatorLights modules search the ship's parts when
5 | /// looking for target modules to interoperate with.
6 | ///
7 | public enum PartSearchStrategy
8 | {
9 | ///
10 | /// Search the host part only (i.e. the part where the module lives).
11 | ///
12 | host,
13 |
14 | ///
15 | /// Search the parent part only (i.e. the direct parent of the part where the module lives).
16 | ///
17 | parent
18 | }
19 |
20 | ///
21 | /// Extension methods for PartSearchStrategy.
22 | ///
23 | internal static class PartSearchStrategies
24 | {
25 | ///
26 | /// The search strategy to use for everything, unless specified otherwise.
27 | ///
28 | public const PartSearchStrategy Default = PartSearchStrategy.host;
29 |
30 | ///
31 | /// Choose the part to use. Returns null if not found.
32 | ///
33 | ///
34 | ///
35 | ///
36 | public static Part ChoosePart(this PartSearchStrategy strategy, PartModule module)
37 | {
38 | if (module == null) return null;
39 | switch (strategy)
40 | {
41 | case PartSearchStrategy.host:
42 | return module.part;
43 |
44 | case PartSearchStrategy.parent:
45 | return (module.part == null) ? null : module.part.parent;
46 |
47 | default:
48 | return null;
49 | }
50 | }
51 |
52 | ///
53 | /// Gets whether the specified candidate part is the chosen part for the specified module.
54 | ///
55 | ///
56 | ///
57 | ///
58 | ///
59 | public static bool IsChoice(this PartSearchStrategy strategy, PartModule module, Part candidatePart)
60 | {
61 | if (module == null) return candidatePart == null;
62 | switch (strategy)
63 | {
64 | case PartSearchStrategy.host:
65 | return false;
66 | case PartSearchStrategy.parent:
67 | return object.ReferenceEquals(candidatePart, ChoosePart(strategy, module));
68 | default:
69 | return false;
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/files/Parts/antennas/communotron16S.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the Communotron-16S antenna.
2 |
3 | @PART[SurfAntenna]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp2
12 | position = 0, 0.056, -0.003
13 | scale = 1.6, 0.5, 0.7
14 | rotation = 0, 0, 0
15 | }
16 |
17 |
18 | //-------------------------------------------------------------------------
19 | // CONTROLLABLE EMISSIVES
20 | //-------------------------------------------------------------------------
21 |
22 | MODULE {
23 | name = ModuleControllableEmissive
24 | target = IndicatorLights/Meshes/squareLamp2
25 | emissiveName = indicator
26 | }
27 |
28 |
29 | //-------------------------------------------------------------------------
30 | // CONTROLLERS
31 | //-------------------------------------------------------------------------
32 |
33 | MODULE {
34 | name = ModuleDataTransmitterIndicator
35 | emissiveName = indicator
36 | // Get really fancy with busy color. This module type exposes one static
37 | // field, dataRate. We'll use a random flicker for the animation (like
38 | // an old-time modem), and we'll plug the data rate both into the flicker
39 | // period (so higher-speed antennas flicker faster), and into the bias
40 | // (so higher-speed antennas spend a greater percentage of their time
41 | // in the "on" state rather than "off").
42 | //
43 | // We don't actually have to use the static syntax here (we could just
44 | // take the data rate for this antenna, do the math, and plug in the
45 | // literal numbers here). However, using the actual static expression
46 | // comes with a few benefits. First, it's more maintainable: we
47 | // can just use the same static expression for all the antennas, rather
48 | // than having to come up with a different expression with different math
49 | // for each one. Second, it's more explicit to anyone reading this just
50 | // *why* the number is what it is. Third, it's more robust: if Squad ever
51 | // tinkers with the data rates, or someone uses ModuleManager to tweak
52 | // them, this will automatically follow suit. Fourth, it's friendlier
53 | // to modders: if you have your own antenna and you want to set it up
54 | // for IndicatorLights compatibility, you can just copy the following
55 | // line verbatim and you'll get behavior that's consistent with what
56 | // IndicatorLights does with the stock antennas.
57 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
58 | }
59 | }
--------------------------------------------------------------------------------
/src/ModuleCrewIndicatorToggle.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// A specialized toggle for turning crew indicators on/off.
5 | ///
6 | public class ModuleCrewIndicatorToggle : PartModule, Identifiers.IIdentifiable, IToggle
7 | {
8 | [KSPField(guiName = "Crew LEDs", isPersistant = true, guiActive = true, guiActiveEditor = true),
9 | UI_Toggle(affectSymCounterparts = UI_Scene.Editor, controlEnabled = true, enabledText = "On", disabledText = "Off")]
10 | public bool status = true;
11 | private BaseField StatusField { get { return Fields["status"]; } }
12 |
13 | [KSPField]
14 | public string toggleName = null;
15 |
16 | ///
17 | /// Determines where the toggle UI is visible.
18 | ///
19 | [KSPField]
20 | public UI_Scene uiToggle = UI_Scene.Editor;
21 |
22 | ///
23 | /// Action-group method for toggling status.
24 | ///
25 | ///
26 | [KSPAction("Toggle Crew LEDs")]
27 | public void OnToggleAction(KSPActionParam actionParam)
28 | {
29 | status = actionParam.type != KSPActionType.Deactivate;
30 | }
31 | private BaseAction ToggleAction { get { return Actions["OnToggleAction"]; } }
32 |
33 | ///
34 | /// Action-group method for setting status to true.
35 | ///
36 | ///
37 | [KSPAction("Activate Crew LEDs")]
38 | public void OnActivateAction(KSPActionParam actionParam)
39 | {
40 | status = true;
41 | }
42 | private BaseAction ActivateAction { get { return Actions["OnActivateAction"]; } }
43 |
44 | ///
45 | /// Action-group method for setting status to false.
46 | ///
47 | ///
48 | [KSPAction("Deactivate Crew LEDs")]
49 | public void OnDeactivateAction(KSPActionParam actionParam)
50 | {
51 | status = false;
52 | }
53 | private BaseAction DeactivateAction { get { return Actions["OnDeactivateAction"]; } }
54 |
55 | public string Identifier
56 | {
57 | get { return toggleName; }
58 | }
59 |
60 | public bool ToggleStatus
61 | {
62 | get { return status; }
63 | }
64 |
65 | public override void OnStart(StartState state)
66 | {
67 | base.OnStart(state);
68 | StatusField.guiActive = uiToggle.IsFlightEnabled();
69 | StatusField.guiActiveEditor = uiToggle.IsEditorEnabled();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/files/Parts/crewable/mk1cabin.cfg:
--------------------------------------------------------------------------------
1 | // Adds occupancy indicators to the Mk1 crew cabin.
2 |
3 | @PART[MK1CrewCabin]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp
12 | scale = 0.6, 0.6, 0.5
13 | position = 0, 0.469, -0.625
14 | rotation = 0, 180, 0
15 | }
16 |
17 | MODEL
18 | {
19 | model = IndicatorLights/Meshes/squareLamp
20 | scale = 0.6, 0.6, 0.5
21 | position = 0, -0.469, -0.625
22 | rotation = 0, 180, 0
23 | }
24 |
25 | //-------------------------------------------------------------------------
26 | // CONTROLLABLE EMISSIVES
27 | //-------------------------------------------------------------------------
28 |
29 | MODULE {
30 | name = ModuleControllableEmissive
31 | target = IndicatorLights/Meshes/squareLamp:0
32 | emissiveName = indicator0
33 | }
34 |
35 | MODULE {
36 | name = ModuleControllableEmissive
37 | target = IndicatorLights/Meshes/squareLamp:1
38 | emissiveName = indicator1
39 | }
40 |
41 | //-------------------------------------------------------------------------
42 | // CONTROLLERS
43 | //-------------------------------------------------------------------------
44 |
45 | MODULE {
46 | name = ModuleCrewIndicatorToggle
47 | toggleName = indicatorToggle
48 | }
49 |
50 | MODULE {
51 | name = ModuleCrewIndicator
52 | controllerName = crewController0
53 | toggleName = indicatorToggle
54 | }
55 |
56 | MODULE {
57 | name = ModuleCrewIndicator
58 | controllerName = crewController1
59 | toggleName = indicatorToggle
60 | }
61 |
62 | MODULE
63 | {
64 | name = ModuleScienceAvailabilityIndicator
65 | controllerName = availability0
66 | experimentID = crewReport
67 | lowValueColor = crewController0
68 | mediumValueColor = highValueColor
69 | highValueColor = blink(lowValueColor, 200, $Off, 200)
70 | }
71 |
72 | MODULE
73 | {
74 | name = ModuleScienceAvailabilityIndicator
75 | controllerName = availability1
76 | experimentID = crewReport
77 | lowValueColor = crewController1
78 | mediumValueColor = highValueColor
79 | highValueColor = blink(lowValueColor, 200, $Off, 200)
80 | }
81 |
82 | MODULE {
83 | name = ModuleScienceDataIndicator
84 | experimentID = crewReport
85 | emissiveName = indicator0
86 | dataColor = crewController0
87 | emptyColor = availability0
88 | }
89 |
90 | MODULE {
91 | name = ModuleScienceDataIndicator
92 | experimentID = crewReport
93 | emissiveName = indicator1
94 | dataColor = crewController1
95 | emptyColor = availability1
96 | }
97 | }
--------------------------------------------------------------------------------
/files/Parts/dockingPorts/smallPort.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the small docking port.
2 |
3 | @PART[dockingPort3]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 Indicator lights display crossfeed status.:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Utility/dockingPortJr/dockingPortJr
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp2
22 | scale = 0.3, 0.6, 0.3
23 | position = -0.32, 0.06, 0
24 | rotation = 0, 0, 8
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/squareLamp2
30 | scale = 0.3, 0.6, 0.3
31 | position = 0.32, 0.06, 0
32 | rotation = 0, 0, -8
33 | }
34 |
35 |
36 | //-------------------------------------------------------------------------
37 | // CONTROLLABLE EMISSIVES
38 | //-------------------------------------------------------------------------
39 | MODULE {
40 | name = ModuleControllableEmissive
41 | target = IndicatorLights/Meshes/squareLamp2
42 | emissiveName = indicator
43 | }
44 |
45 |
46 | //-------------------------------------------------------------------------
47 | // CONTROLLERS
48 | //-------------------------------------------------------------------------
49 |
50 | // Controls the light manually.
51 | MODULE {
52 | name = ModuleToggleLED
53 | activeColor = ModuleDockingCrossfeedIndicator
54 | inactiveColor = $Off
55 | defaultActionGroup = Light
56 | }
57 |
58 | // This provides detection of the docking port state. We don't specify an
59 | // emissiveName here because it's not controlling the light directly (we're
60 | // just using it as an input to other modules).
61 | MODULE {
62 | name = ModuleDockingCrossfeedIndicator
63 | }
64 |
65 | // This detects the docking state. We make this the "root" controller that
66 | // actually drives the emissive color, because we want the indicator to blink
67 | // when it's acquiring or disengaging, regardless of the toggle setting.
68 | // If we're in the "ready" (or docked) state, then we'll take our input
69 | // from the toggle.
70 | MODULE {
71 | name = ModuleDockingStateIndicator
72 | emissiveName = indicator
73 | readyColor = ModuleToggleLED
74 | acquireColor = blink(ModuleDockingCrossfeedIndicator, 100, $Off, 100)
75 | disengageColor = blink(ModuleDockingCrossfeedIndicator, 120, $Off, 1080)
76 | }
77 | }
--------------------------------------------------------------------------------
/examples/VesselSituation.cfg:
--------------------------------------------------------------------------------
1 | // Demonstrate the use of situation() syntax.
2 | //
3 | // This example adds lights to the HECS2 probe core, which light up in
4 | // various vessel situations (see comments below).
5 |
6 | @PART[HECS2_ProbeCore] {
7 |
8 | //-------------------------------------------------------------------------
9 | // INDICATOR MESHES
10 | //-------------------------------------------------------------------------
11 |
12 | MODEL
13 | {
14 | model = IndicatorLights/Meshes/nubbinLamp
15 | scale = 1.5, 1.5, 0.6
16 | position = -0.1, 0.02, -0.73
17 | rotation = 0, 180, 0
18 | }
19 |
20 | MODEL
21 | {
22 | model = IndicatorLights/Meshes/nubbinLamp
23 | scale = 1.5, 1.5, 0.6
24 | position = 0, 0.02, -0.73
25 | rotation = 0, 180, 0
26 | }
27 |
28 | MODEL
29 | {
30 | model = IndicatorLights/Meshes/nubbinLamp
31 | scale = 1.5, 1.5, 0.6
32 | position = 0.1, 0.02, -0.73
33 | rotation = 0, 180, 0
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLABLE EMISSIVES
39 | //-------------------------------------------------------------------------
40 |
41 | // This emissive shows status when we're on the surface.
42 | MODULE {
43 | name = ModuleControllableEmissive
44 | target = IndicatorLights/Meshes/nubbinLamp:0
45 | emissiveName = surface
46 | }
47 |
48 | // This emissive shows status when we're flying (not on the surface,
49 | // but not in space).
50 | MODULE {
51 | name = ModuleControllableEmissive
52 | target = IndicatorLights/Meshes/nubbinLamp:1
53 | emissiveName = airborne
54 | }
55 |
56 | // This emissive shows status when we're in space.
57 | MODULE {
58 | name = ModuleControllableEmissive
59 | target = IndicatorLights/Meshes/nubbinLamp:2
60 | emissiveName = space
61 | }
62 |
63 |
64 | //-------------------------------------------------------------------------
65 | // CONTROLLERS
66 | //-------------------------------------------------------------------------
67 |
68 | // This controls the surface indicator. Green when on dry land, blue
69 | // when splashed.
70 | MODULE {
71 | name = ModuleBooleanIndicator
72 | input = situation(LANDED, SPLASHED)
73 | emissiveName = surface
74 | activeColor = if(situation(LANDED), $ToggleLED, #0040FF)
75 | }
76 |
77 | // This controls the indicator for when we're flying.
78 | MODULE {
79 | name = ModuleBooleanIndicator
80 | input = situation(FLYING)
81 | emissiveName = airborne
82 | }
83 |
84 | // Rapid blinking for suborbital. Pulsating for escape. Solid for orbit.
85 | MODULE {
86 | name = ModuleBooleanIndicator
87 | input = situation(SUB_ORBITAL, ORBITING, ESCAPING)
88 | emissiveName = space
89 | activeColor = if(situation(ORBITING), $ToggleLED, if(situation(SUB_ORBITAL), blink($ToggleLED, 200, $Off, 200), pulsate($ToggleLED, 1000, 0.5)))
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/files/Parts/crewable/cupola.cfg:
--------------------------------------------------------------------------------
1 | // Adds an occupancy indicator to the crew cupola.
2 |
3 | @PART[cupola]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Command/cupola/model
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 1, 0.25, 0.5
23 | position = 0, -0.157, -1.353
24 | rotation = 0, 180, 0
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleControllableEmissive
33 | target = IndicatorLights/Meshes/squareLamp
34 | emissiveName = indicator
35 | }
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleCrewIndicatorToggle
43 | toggleName = indicatorToggle
44 | }
45 |
46 | MODULE {
47 | name = ModuleCrewIndicator
48 | toggleName = indicatorToggle
49 | }
50 |
51 | MODULE
52 | {
53 | name = ModuleScienceAvailabilityIndicator
54 | experimentID = crewReport
55 | lowValueColor = ModuleCrewIndicator
56 | mediumValueColor = highValueColor
57 | highValueColor = blink(lowValueColor, 200, $Off, 200)
58 | }
59 |
60 | MODULE {
61 | name = ModuleScienceDataIndicator
62 | experimentID = crewReport
63 | emissiveName = indicator
64 | dataColor = ModuleCrewIndicator
65 | emptyColor = ModuleScienceAvailabilityIndicator
66 | }
67 |
68 |
69 | //-------------------------------------------------------------------------
70 | // TWEAKS
71 | //-------------------------------------------------------------------------
72 |
73 | // This pod uses a ModuleColorChanger to handle its cabin lights, set up
74 | // so that by default it takes control of *all* emissives on the part.
75 | // Need to tell it not to tinker with the meshes that we're adding here;
76 | // otherwise, the crew indicator will just turn on and off with the cabin
77 | // lights instead of actually working as a crew indicator.
78 | @MODULE[ModuleColorChanger] {
79 | excludedRenderer = IndicatorLights/Meshes/squareLamp(Clone)
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Loader.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Runs once when the game hits the main menu on startup. Loads custom IndicatorLights
7 | /// config used in various places.
8 | ///
9 | [KSPAddon(KSPAddon.Startup.MainMenu, true)]
10 | public class Loader : MonoBehaviour
11 | {
12 | private const string MASTER_NODE_NAME = "IndicatorLights";
13 |
14 | private delegate void ConfigLoader(ConfigNode node);
15 |
16 | ///
17 | /// Here when the script starts up.
18 | ///
19 | public void Start()
20 | {
21 | Configuration.Initialize();
22 | UrlDir.UrlConfig[] configs = GameDatabase.Instance.GetConfigs(MASTER_NODE_NAME);
23 | if (configs.Length < 1)
24 | {
25 | Logging.Error("Can't find main " + MASTER_NODE_NAME + " config node! Some features will be inoperable.");
26 | return;
27 | }
28 | ConfigNode masterNode = configs[0].config;
29 | ProcessMasterNode(masterNode);
30 |
31 | // Community Trait Icons integration. If initCTIWrapper returns true,
32 | // it means that Community Trait Icons has been identified as being
33 | // loaded, and therefore we can load its colors.
34 | if (Compatibility.CTIWrapper.initCTIWrapper())
35 | {
36 | StartCoroutine(ModuleCrewIndicator.LoadCommunityTraitIconColors());
37 | }
38 | }
39 |
40 | ///
41 | /// Process the main IndicatorLights config node.
42 | ///
43 | ///
44 | private static void ProcessMasterNode(ConfigNode masterNode)
45 | {
46 | TryProcessChildNode(masterNode, ModuleCrewIndicator.CONFIG_NODE_NAME, ModuleCrewIndicator.LoadConfig);
47 | }
48 |
49 | ///
50 | /// Looks for a child with the specified name, and delegates to it if found.
51 | ///
52 | ///
53 | ///
54 | ///
55 | private static void TryProcessChildNode(ConfigNode masterNode, string childName, ConfigLoader loader)
56 | {
57 | ConfigNode child = masterNode.nodes.GetNode(childName);
58 | if (child == null)
59 | {
60 | Logging.Warn("Child node " + childName + " of master config node " + MASTER_NODE_NAME + " not found, skipping");
61 | }
62 | else
63 | {
64 | Logging.Log("Loading " + masterNode.name + " config: " + child.name);
65 | loader(child);
66 | }
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/files/Parts/crewable/mk1can.cfg:
--------------------------------------------------------------------------------
1 | // Adds an occupancy indicator to the Mk1 lander can.
2 |
3 | @PART[landerCabinSmall]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Command/mk1LanderCan/model
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 1, 0.25, 0.5
23 | position = 0, -0.2737, -0.8592
24 | rotation = 0, 180, 0
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleControllableEmissive
33 | target = IndicatorLights/Meshes/squareLamp
34 | emissiveName = indicator
35 | }
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleCrewIndicatorToggle
43 | toggleName = indicatorToggle
44 | }
45 |
46 | MODULE {
47 | name = ModuleCrewIndicator
48 | toggleName = indicatorToggle
49 | }
50 |
51 | MODULE
52 | {
53 | name = ModuleScienceAvailabilityIndicator
54 | experimentID = crewReport
55 | lowValueColor = ModuleCrewIndicator
56 | mediumValueColor = highValueColor
57 | highValueColor = blink(lowValueColor, 200, $Off, 200)
58 | }
59 |
60 | MODULE {
61 | name = ModuleScienceDataIndicator
62 | experimentID = crewReport
63 | emissiveName = indicator
64 | dataColor = ModuleCrewIndicator
65 | emptyColor = ModuleScienceAvailabilityIndicator
66 | }
67 |
68 |
69 | //-------------------------------------------------------------------------
70 | // TWEAKS
71 | //-------------------------------------------------------------------------
72 |
73 | // This pod uses a ModuleColorChanger to handle its cabin lights, set up
74 | // so that by default it takes control of *all* emissives on the part.
75 | // Need to tell it not to tinker with the meshes that we're adding here;
76 | // otherwise, the crew indicator will just turn on and off with the cabin
77 | // lights instead of actually working as a crew indicator.
78 | @MODULE[ModuleColorChanger] {
79 | excludedRenderer = IndicatorLights/Meshes/squareLamp(Clone)
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/files/Parts/antennas/largeRelayDish.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the large relay dish.
2 |
3 | @PART[RelayAntenna100]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/nubbinLamp
12 | position = 0, 1.25, 0
13 | scale = 5.7, 5.7, 5
14 | rotation = -90, 0, 0
15 | }
16 |
17 | MODEL
18 | {
19 | model = IndicatorLights/Meshes/nubbinLamp
20 | position = 0, 2.252, -0.07
21 | scale = 1.65, 1.65, 2
22 | rotation = -90, 0, 0
23 | }
24 |
25 |
26 | //-------------------------------------------------------------------------
27 | // CONTROLLABLE EMISSIVES
28 | //-------------------------------------------------------------------------
29 |
30 | MODULE {
31 | name = ModuleControllableEmissive
32 | target = IndicatorLights/Meshes/nubbinLamp
33 | emissiveName = indicator
34 | }
35 |
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleDataTransmitterIndicator
43 | emissiveName = indicator
44 | // Get really fancy with busy color. This module type exposes one static
45 | // field, dataRate. We'll use a random flicker for the animation (like
46 | // an old-time modem), and we'll plug the data rate both into the flicker
47 | // period (so higher-speed antennas flicker faster), and into the bias
48 | // (so higher-speed antennas spend a greater percentage of their time
49 | // in the "on" state rather than "off").
50 | //
51 | // We don't actually have to use the static syntax here (we could just
52 | // take the data rate for this antenna, do the math, and plug in the
53 | // literal numbers here). However, using the actual static expression
54 | // comes with a few benefits. First, it's more maintainable: we
55 | // can just use the same static expression for all the antennas, rather
56 | // than having to come up with a different expression with different math
57 | // for each one. Second, it's more explicit to anyone reading this just
58 | // *why* the number is what it is. Third, it's more robust: if Squad ever
59 | // tinkers with the data rates, or someone uses ModuleManager to tweak
60 | // them, this will automatically follow suit. Fourth, it's friendlier
61 | // to modders: if you have your own antenna and you want to set it up
62 | // for IndicatorLights compatibility, you can just copy the following
63 | // line verbatim and you'll get behavior that's consistent with what
64 | // IndicatorLights does with the stock antennas.
65 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
66 | }
67 | }
--------------------------------------------------------------------------------
/src/ModuleDataTransmitterIndicator.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace IndicatorLights
4 | {
5 | ///
6 | /// Module that shows when an antenna is transmitting data.
7 | ///
8 | class ModuleDataTransmitterIndicator : ModuleSourceIndicator, IToggle
9 | {
10 | private IColorSource busySource;
11 | private IColorSource inactiveSource;
12 | private ModuleDeployableAntenna deployable = null;
13 |
14 | ///
15 | /// The data rate of the transmitter, in mits/second.
16 | ///
17 | [StaticField]
18 | private double dataRate;
19 |
20 | /*
21 | To put things in perspective, here are the data rates of the stock KSP antennas, as of KSP 1.2:
22 |
23 | RA-2: 2.86
24 | Communotron 16: 3.33
25 | Communotron 16-S: 3.33
26 | DTS-M1: 5.71
27 | HG-5: 5.71
28 | RA-15: 5.71
29 | RA-100: 11.43
30 | 88-88: 20.00
31 | HG-55: 20.00
32 | */
33 |
34 | ///
35 | /// The color to display when the transmitter is busy.
36 | ///
37 | [KSPField]
38 | [ColorSourceIDField]
39 | public string busyColor = ColorSources.Random(
40 | ColorSources.Constant(DefaultColor.ToggleLED),
41 | ColorSources.Constant(DefaultColor.Off),
42 | 100,
43 | 0.5)
44 | .ColorSourceID;
45 |
46 | ///
47 | /// The color to display when the transmitter is idle.
48 | ///
49 | [KSPField]
50 | [ColorSourceIDField]
51 | public string inactiveColor = ColorSources.Constant(DefaultColor.Off).ColorSourceID;
52 |
53 | public override void OnStart(StartState state)
54 | {
55 | base.OnStart(state);
56 |
57 | deployable = part.FindModuleImplementing(); // may be null
58 | }
59 |
60 | public override void ParseIDs()
61 | {
62 | base.ParseIDs();
63 | dataRate = (SourceModule == null) ? 0.0 : SourceModule.DataRate;
64 | busySource = FindColorSource(busyColor);
65 | inactiveSource = FindColorSource(inactiveColor);
66 | }
67 |
68 | public override Color OutputColor
69 | {
70 | get
71 | {
72 | return (ToggleStatus ? busySource : inactiveSource).OutputColor;
73 | }
74 | }
75 |
76 | public bool ToggleStatus
77 | {
78 | get
79 | {
80 | return ((deployable == null) || (deployable.deployState == ModuleDeployablePart.DeployState.EXTENDED))
81 | && (SourceModule != null) && SourceModule.IsBusy();
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/ModuleBooleanIndicator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace IndicatorLights
5 | {
6 | ///
7 | /// A bi-state indicator whose output is controlled by other toggle controllers.
8 | ///
9 | class ModuleBooleanIndicator : ModuleEmissiveController, IToggle
10 | {
11 | ///
12 | /// Required. Specifies the input toggle that controls this module. Could be a simple
13 | /// identifier (such as a module or controller name), or it could be parseable toggle
14 | /// syntax such as "and(toggle1, !toggle2)".
15 | ///
16 | [KSPField]
17 | [ToggleIDField]
18 | public string input = string.Empty;
19 |
20 | ///
21 | /// Color used when in the "on" state.
22 | ///
23 | [KSPField]
24 | [ColorSourceIDField]
25 | public string activeColor = Colors.ToString(DefaultColor.ToggleLED);
26 |
27 | ///
28 | /// Color used when in the "off" state.
29 | ///
30 | [KSPField]
31 | [ColorSourceIDField]
32 | public string inactiveColor = Colors.ToString(DefaultColor.Off);
33 |
34 | bool isValid = false;
35 | private IToggle inputToggle = null;
36 | private IColorSource activeSource = null;
37 | private IColorSource inactiveSource = null;
38 |
39 | public override void ParseIDs()
40 | {
41 | base.ParseIDs();
42 |
43 | try
44 | {
45 | inputToggle = RequireToggle(input);
46 | isValid = true;
47 | }
48 | catch (ArgumentException e)
49 | {
50 | Logging.Warn("Invalid input for " + Identifier + " on " + part.GetTitle() + ": " + e.Message);
51 | }
52 | activeSource = FindColorSource(activeColor);
53 | inactiveSource = FindColorSource(inactiveColor);
54 | }
55 |
56 | public override bool HasColor
57 | {
58 | get
59 | {
60 | return CurrentSource.HasColor;
61 | }
62 | }
63 |
64 | public override Color OutputColor
65 | {
66 | get
67 | {
68 | return CurrentSource.OutputColor;
69 | }
70 | }
71 |
72 | ///
73 | /// IToggle implementation.
74 | ///
75 | public bool ToggleStatus
76 | {
77 | get
78 | {
79 | return isValid ? inputToggle.ToggleStatus : false;
80 | }
81 | }
82 |
83 | private IColorSource CurrentSource
84 | {
85 | get
86 | {
87 | if (!isValid) return ColorSources.ERROR;
88 | return ToggleStatus ? activeSource : inactiveSource;
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/ModuleEmissiveController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 |
4 | namespace IndicatorLights
5 | {
6 | ///
7 | /// Base class for "simple" emissive controller modules that have only a single
8 | /// output color.
9 | ///
10 | /// Note that there may be multiple controllers targeting the same emissive.
11 | ///
12 | public abstract class ModuleEmissiveController : ModuleEmissiveControllerBase, IColorSource, Identifiers.IIdentifiable
13 | {
14 | ///
15 | /// This is used to uniquely identify a particular controller. Use the ControllerName
16 | /// property to access at run time. If not specified, ControllerName will simply
17 | /// return the name of the class.
18 | ///
19 | /// The use case for this property is if you want to have a controller that specifies
20 | /// an output color, but doesn't actually point at any emissiveName that it controls.
21 | /// This can be useful if you want to have "compound controllers", where the output
22 | /// from one controller serves as an input for another.
23 | ///
24 | [KSPField]
25 | public string controllerName = null;
26 |
27 | ///
28 | /// Call this at runtime to identify the controller.
29 | ///
30 | public string ColorSourceID
31 | {
32 | get
33 | {
34 | return string.IsNullOrEmpty(controllerName) ? GetType().Name : controllerName;
35 | }
36 | }
37 |
38 | ///
39 | /// Gets whether this controller has an output color available. Default implementation
40 | /// is to return true. The contract is that if this returns false, should not try to
41 | /// get the OutputColor.
42 | ///
43 | public virtual bool HasColor
44 | {
45 | get { return true; }
46 | }
47 |
48 | ///
49 | /// Gets the output color of this controller. Won't be called unless HasColor
50 | /// returns true.
51 | ///
52 | public abstract Color OutputColor { get; }
53 |
54 | ///
55 | /// Called on every frame when it's time to set colors on the controllable emissives.
56 | ///
57 | protected override void SetColors()
58 | {
59 | if (HasColor)
60 | {
61 | List controlledEmissives = Emissives;
62 | for (int i = 0; i < controlledEmissives.Count; ++i)
63 | {
64 | controlledEmissives[i].Color = OutputColor;
65 | }
66 | }
67 | }
68 |
69 | public string Identifier
70 | {
71 | get
72 | {
73 | return ColorSourceID;
74 | }
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/src/ColorSourceArray.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Lazy-loading placeholder for an array of color sources, useful for emissive
5 | /// controllers that work with arrays of meshes.
6 | ///
7 | internal class ColorSourceArray
8 | {
9 | private readonly string colorSourceID;
10 | private IColorSource[] sources = null;
11 | private bool isValid = false;
12 | private bool isInitialized = false;
13 |
14 | private ColorSourceArray(string colorSourceID)
15 | {
16 | this.colorSourceID = colorSourceID;
17 | }
18 |
19 | ///
20 | /// Get a ColorSourceArray for the specified ID.
21 | ///
22 | ///
23 | ///
24 | public static ColorSourceArray of(string colorSourceID)
25 | {
26 | return new ColorSourceArray(colorSourceID);
27 | }
28 |
29 | ///
30 | /// Try to set the colors of the meshes on the specified controller.
31 | ///
32 | ///
33 | public void SetColors(ModuleEmissiveControllerBase controller)
34 | {
35 | if (!TryInitialize(controller)) return;
36 |
37 | int sourceIndex = 0;
38 | for (int emissiveIndex = 0; emissiveIndex < controller.Emissives.Count; ++emissiveIndex)
39 | {
40 | ModuleControllableEmissive emissive = controller.Emissives[emissiveIndex];
41 | for (int meshIndex = 0; meshIndex < emissive.Count; ++meshIndex)
42 | {
43 | if (sourceIndex >= sources.Length) return;
44 | IColorSource source = sources[sourceIndex++];
45 | if (source.HasColor) emissive.SetColorAt(source.OutputColor, meshIndex);
46 | }
47 | }
48 | }
49 |
50 | private bool TryInitialize(ModuleEmissiveControllerBase controller)
51 | {
52 | if (isInitialized) return isValid;
53 | if ((controller == null) || (controller.Emissives == null) || (controller.Emissives.Count == 0)) return DoneInitializing(false);
54 | int total = 0;
55 | for (int emissiveIndex = 0; emissiveIndex < controller.Emissives.Count; ++emissiveIndex)
56 | {
57 | int count = controller.Emissives[emissiveIndex].Count;
58 | if (count < 0) return false; // not yet initialized, we'll try again later
59 | total += count;
60 | }
61 | if (total < 1) return DoneInitializing(false);
62 |
63 | sources = ColorSources.FindWithIndex(controller, colorSourceID, total);
64 | return DoneInitializing(true);
65 | }
66 |
67 | private bool DoneInitializing(bool success)
68 | {
69 | isValid = success;
70 | isInitialized = true;
71 | return isValid;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/files/Parts/science/scienceJr.cfg:
--------------------------------------------------------------------------------
1 | @PART[science_module]:FOR[IndicatorLights]
2 | {
3 | // We have to re-specify the model for the stock part, because this is
4 | // an older part that uses the "mesh =" syntax in its .cfg file instead
5 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
6 | // multiple models as part of the same part, which would prevent this mod
7 | // from adding meshes for the indicator lights.
8 | MODEL
9 | {
10 | model = Squad/Parts/Science/MaterialBay/science_module_small
11 | }
12 |
13 |
14 | //-------------------------------------------------------------------------
15 | // INDICATOR MESHES
16 | //-------------------------------------------------------------------------
17 |
18 | MODEL
19 | {
20 | model = IndicatorLights/Meshes/squareLamp
21 | scale = 1, 0.4, 0.5
22 | position = 0, -0.34833, -0.49839
23 | rotation = 0, 180, 0
24 | }
25 |
26 | MODEL
27 | {
28 | model = IndicatorLights/Meshes/squareLamp
29 | scale = 1, 0.4, 0.5
30 | position = 0, -0.34833, 0.49839
31 | rotation = 0, 0, 0
32 | }
33 |
34 |
35 | //-------------------------------------------------------------------------
36 | // CONTROLLABLE EMISSIVES
37 | //-------------------------------------------------------------------------
38 |
39 | // The add-on meshes that we use to show science content, availability, etc.
40 | MODULE {
41 | name = ModuleControllableEmissive
42 | target = IndicatorLights/Meshes/squareLamp
43 | emissiveName = indicator
44 | }
45 |
46 | // The bluish-glowing center part (from the original model)
47 | MODULE {
48 | name = ModuleControllableEmissive
49 | target = Glass
50 | emissiveName = frontPanel
51 | }
52 |
53 | // The orangey-glowing side parts (from the original model)
54 | MODULE {
55 | name = ModuleControllableEmissive
56 | target = DoorAssembly
57 | emissiveName = sidePanels
58 | }
59 |
60 |
61 | //-------------------------------------------------------------------------
62 | // CONTROLLERS
63 | //-------------------------------------------------------------------------
64 |
65 | // These first two controllers take care of the add-on meshes.
66 | MODULE {
67 | name = ModuleScienceDataIndicator
68 | emissiveName = indicator
69 | dataColor = $HighScience
70 | partialDataColor = $MediumScience
71 | lowDataColor = $LowScience
72 | emptyColor = ModuleScienceAvailabilityIndicator
73 | lowScienceThreshold = 0.25
74 | highScienceThreshold = 0.8
75 | }
76 |
77 | MODULE {
78 | name = ModuleScienceAvailabilityIndicator
79 | lowScienceThreshold = 0.25
80 | highScienceThreshold = 0.8
81 | }
82 |
83 | // Make the blue glowy part pulsate slowly when it has science.
84 | MODULE {
85 | name = ModuleScienceDataIndicator
86 | emissiveName = frontPanel
87 | dataColor = pulsate(#00FFFF, 2800, 1, 0.4)
88 | emptyColor = #004040
89 | }
90 |
91 | // Make the orange glowy part pulsate quickly when it has science.
92 | MODULE {
93 | name = ModuleScienceDataIndicator
94 | emissiveName = sidePanels
95 | dataColor = pulsate(#FF8000, 777, 1, 0.7)
96 | emptyColor = #804500
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/files/Parts/dockingPorts/mediumPort.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the medium docking port.
2 |
3 | @PART[dockingPort2]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 Indicator lights display crossfeed status.:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Utility/dockingPort/dockingPort
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp2
22 | scale = 1, 1, 0.3
23 | position = -0.5331, 0.10, 0
24 | rotation = 0, 0, 20
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/squareLamp2
30 | scale = 1, 1, 0.3
31 | position = 0.5331, 0.10, 0
32 | rotation = 0, 0, -20
33 | }
34 |
35 | MODEL
36 | {
37 | model = IndicatorLights/Meshes/squareLamp2
38 | scale = 0.3, 1, 1
39 | position = 0, 0.08, -0.5331
40 | rotation = -20, 0, 0
41 | }
42 |
43 | MODEL
44 | {
45 | model = IndicatorLights/Meshes/squareLamp2
46 | scale = 0.3, 1, 1
47 | position = 0, 0.08, 0.5331
48 | rotation = 20, 0, 0
49 | }
50 |
51 |
52 | //-------------------------------------------------------------------------
53 | // CONTROLLABLE EMISSIVES
54 | //-------------------------------------------------------------------------
55 | MODULE {
56 | name = ModuleControllableEmissive
57 | target = IndicatorLights/Meshes/squareLamp2
58 | emissiveName = indicator
59 | }
60 |
61 |
62 | //-------------------------------------------------------------------------
63 | // CONTROLLERS
64 | //-------------------------------------------------------------------------
65 |
66 | // Controls the light manually.
67 | MODULE {
68 | name = ModuleToggleLED
69 | activeColor = ModuleDockingCrossfeedIndicator
70 | inactiveColor = $Off
71 | defaultActionGroup = Light
72 | }
73 |
74 | // This provides detection of the docking port state. We don't specify an
75 | // emissiveName here because it's not controlling the light directly (we're
76 | // just using it as an input to other modules).
77 | MODULE {
78 | name = ModuleDockingCrossfeedIndicator
79 | }
80 |
81 | // This detects the docking state. We make this the "root" controller that
82 | // actually drives the emissive color, because we want the indicator to blink
83 | // when it's acquiring or disengaging, regardless of the toggle setting.
84 | // If we're in the "ready" (or docked) state, then we'll take our input
85 | // from the toggle.
86 | MODULE {
87 | name = ModuleDockingStateIndicator
88 | emissiveName = indicator
89 | readyColor = ModuleToggleLED
90 | acquireColor = blink(ModuleDockingCrossfeedIndicator, 100, $Off, 100)
91 | disengageColor = blink(ModuleDockingCrossfeedIndicator, 120, $Off, 1080)
92 | }
93 | }
--------------------------------------------------------------------------------
/files/Parts/antennas/88-88.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the 88-88 dish antenna.
2 |
3 | @PART[commDish]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Utility/commDish88-88/model
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/nubbinLamp
22 | position = 0, -0.143, 0
23 | scale = 5.7, 5.7, 6
24 | rotation = -90, 0, 0
25 | }
26 |
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLABLE EMISSIVES
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleControllableEmissive
34 | target = IndicatorLights/Meshes/nubbinLamp
35 | emissiveName = indicator
36 | }
37 |
38 |
39 | //-------------------------------------------------------------------------
40 | // CONTROLLERS
41 | //-------------------------------------------------------------------------
42 |
43 | MODULE {
44 | name = ModuleDataTransmitterIndicator
45 | emissiveName = indicator
46 | // Get really fancy with busy color. This module type exposes one static
47 | // field, dataRate. We'll use a random flicker for the animation (like
48 | // an old-time modem), and we'll plug the data rate both into the flicker
49 | // period (so higher-speed antennas flicker faster), and into the bias
50 | // (so higher-speed antennas spend a greater percentage of their time
51 | // in the "on" state rather than "off").
52 | //
53 | // We don't actually have to use the static syntax here (we could just
54 | // take the data rate for this antenna, do the math, and plug in the
55 | // literal numbers here). However, using the actual static expression
56 | // comes with a few benefits. First, it's more maintainable: we
57 | // can just use the same static expression for all the antennas, rather
58 | // than having to come up with a different expression with different math
59 | // for each one. Second, it's more explicit to anyone reading this just
60 | // *why* the number is what it is. Third, it's more robust: if Squad ever
61 | // tinkers with the data rates, or someone uses ModuleManager to tweak
62 | // them, this will automatically follow suit. Fourth, it's friendlier
63 | // to modders: if you have your own antenna and you want to set it up
64 | // for IndicatorLights compatibility, you can just copy the following
65 | // line verbatim and you'll get behavior that's consistent with what
66 | // IndicatorLights does with the stock antennas.
67 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
68 | }
69 | }
--------------------------------------------------------------------------------
/files/Parts/antennas/communotron16.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the Communotron-16 antenna.
2 |
3 | @PART[longAntenna]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Utility/commsDish16/model
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/nubbinLamp
22 | position = 0, 0, 0
23 | scale = 1.6, 1.6, 2.5
24 | rotation = -90, 0, 0
25 | }
26 |
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLABLE EMISSIVES
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleControllableEmissive
34 | target = IndicatorLights/Meshes/nubbinLamp
35 | emissiveName = indicator
36 | }
37 |
38 |
39 | //-------------------------------------------------------------------------
40 | // CONTROLLERS
41 | //-------------------------------------------------------------------------
42 |
43 | MODULE {
44 | name = ModuleDataTransmitterIndicator
45 | emissiveName = indicator
46 | // Get really fancy with busy color. This module type exposes one static
47 | // field, dataRate. We'll use a random flicker for the animation (like
48 | // an old-time modem), and we'll plug the data rate both into the flicker
49 | // period (so higher-speed antennas flicker faster), and into the bias
50 | // (so higher-speed antennas spend a greater percentage of their time
51 | // in the "on" state rather than "off").
52 | //
53 | // We don't actually have to use the static syntax here (we could just
54 | // take the data rate for this antenna, do the math, and plug in the
55 | // literal numbers here). However, using the actual static expression
56 | // comes with a few benefits. First, it's more maintainable: we
57 | // can just use the same static expression for all the antennas, rather
58 | // than having to come up with a different expression with different math
59 | // for each one. Second, it's more explicit to anyone reading this just
60 | // *why* the number is what it is. Third, it's more robust: if Squad ever
61 | // tinkers with the data rates, or someone uses ModuleManager to tweak
62 | // them, this will automatically follow suit. Fourth, it's friendlier
63 | // to modders: if you have your own antenna and you want to set it up
64 | // for IndicatorLights compatibility, you can just copy the following
65 | // line verbatim and you'll get behavior that's consistent with what
66 | // IndicatorLights does with the stock antennas.
67 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
68 | }
69 | }
--------------------------------------------------------------------------------
/files/Parts/antennas/dtsM1.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the DTS-M1 antenna.
2 |
3 | @PART[mediumDishAntenna]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Utility/commsAntennaDTS-M1/mediumDishAntenna
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp2
22 | position = 0.008, -0.0037, -0.4955
23 | scale = 1.8, 0.5, 0.5
24 | rotation = -40, 0, 0
25 | }
26 |
27 |
28 | //-------------------------------------------------------------------------
29 | // CONTROLLABLE EMISSIVES
30 | //-------------------------------------------------------------------------
31 |
32 | MODULE {
33 | name = ModuleControllableEmissive
34 | target = IndicatorLights/Meshes/squareLamp2
35 | emissiveName = indicator
36 | }
37 |
38 |
39 | //-------------------------------------------------------------------------
40 | // CONTROLLERS
41 | //-------------------------------------------------------------------------
42 |
43 | MODULE {
44 | name = ModuleDataTransmitterIndicator
45 | emissiveName = indicator
46 | // Get really fancy with busy color. This module type exposes one static
47 | // field, dataRate. We'll use a random flicker for the animation (like
48 | // an old-time modem), and we'll plug the data rate both into the flicker
49 | // period (so higher-speed antennas flicker faster), and into the bias
50 | // (so higher-speed antennas spend a greater percentage of their time
51 | // in the "on" state rather than "off").
52 | //
53 | // We don't actually have to use the static syntax here (we could just
54 | // take the data rate for this antenna, do the math, and plug in the
55 | // literal numbers here). However, using the actual static expression
56 | // comes with a few benefits. First, it's more maintainable: we
57 | // can just use the same static expression for all the antennas, rather
58 | // than having to come up with a different expression with different math
59 | // for each one. Second, it's more explicit to anyone reading this just
60 | // *why* the number is what it is. Third, it's more robust: if Squad ever
61 | // tinkers with the data rates, or someone uses ModuleManager to tweak
62 | // them, this will automatically follow suit. Fourth, it's friendlier
63 | // to modders: if you have your own antenna and you want to set it up
64 | // for IndicatorLights compatibility, you can just copy the following
65 | // line verbatim and you'll get behavior that's consistent with what
66 | // IndicatorLights does with the stock antennas.
67 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
68 | }
69 | }
--------------------------------------------------------------------------------
/src/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace IndicatorLights
5 | {
6 | ///
7 | /// Convenient place for putting extension logic that doesn't particularly have an
8 | /// obvious home elsewhere.
9 | ///
10 | internal static class Extensions
11 | {
12 | ///
13 | /// Gets whether the given UI_Scene value should be enabled in the flight scene.
14 | ///
15 | ///
16 | ///
17 | public static bool IsFlightEnabled(this UI_Scene scene)
18 | {
19 | switch (scene)
20 | {
21 | case UI_Scene.Editor:
22 | case UI_Scene.None:
23 | return false;
24 | default:
25 | return true;
26 | }
27 | }
28 |
29 | ///
30 | /// Gets whether the given UI_Scene value should be enabled in the flight scene.
31 | ///
32 | ///
33 | ///
34 | public static bool IsEditorEnabled(this UI_Scene scene)
35 | {
36 | switch (scene)
37 | {
38 | case UI_Scene.Flight:
39 | case UI_Scene.None:
40 | return false;
41 | default:
42 | return true;
43 | }
44 | }
45 |
46 | ///
47 | /// Get a sub-array of the provided array, starting at the specified index.
48 | ///
49 | ///
50 | ///
51 | ///
52 | ///
53 | public static T[] SubArray(this T[] array, int startIndex)
54 | {
55 | if (startIndex == 0) return array;
56 | if ((startIndex < 0) || (startIndex > array.Length))
57 | {
58 | throw new ArgumentOutOfRangeException(
59 | "startIndex",
60 | startIndex,
61 | "Array index out of range");
62 | }
63 |
64 | T[] result = new T[array.Length - startIndex];
65 | for (int i = 0; i < result.Length; ++i)
66 | {
67 | result[i] = array[i + startIndex];
68 | }
69 | return result;
70 | }
71 |
72 | ///
73 | /// Joins an array of strings into a single string, using the specified joiner.
74 | ///
75 | ///
76 | ///
77 | ///
78 | public static string Join(this string[] array, string joiner)
79 | {
80 | if (array.Length < 1) return string.Empty;
81 | if (array.Length < 2) return array[0];
82 | StringBuilder builder = new StringBuilder(array[0]);
83 | for (int i = 1; i < array.Length; ++i)
84 | {
85 | builder.Append(joiner).Append(array[i]);
86 | }
87 | return builder.ToString();
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/files/Parts/crewable/scienceLab.cfg:
--------------------------------------------------------------------------------
1 | // Adds occupancy indicators to the large science lab.
2 |
3 | @PART[Large_Crewed_Lab]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Science/LargeCrewedLab/large_crewed_lab
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 1, 0.25, 0.5
23 | position = 0, -0.26, -1.274
24 | rotation = 0, 180, 0
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/squareLamp
30 | scale = 1, 0.25, 0.5
31 | position = 0, -0.26, 1.285
32 | rotation = 0, 0, 0
33 | }
34 |
35 | MODEL
36 | {
37 | model = IndicatorLights/Meshes/squareLamp
38 | scale = 1, 0.25, 0.5
39 | position = 0, 0.26, -1.274
40 | rotation = 0, 180, 0
41 | }
42 |
43 | MODEL
44 | {
45 | model = IndicatorLights/Meshes/squareLamp
46 | scale = 1, 0.25, 0.5
47 | position = 0, 0.26, 1.285
48 | rotation = 0, 0, 0
49 | }
50 |
51 | //-------------------------------------------------------------------------
52 | // CONTROLLABLE EMISSIVES
53 | //-------------------------------------------------------------------------
54 |
55 | MODULE {
56 | name = ModuleControllableEmissive
57 | target = IndicatorLights/Meshes/squareLamp:0,1
58 | emissiveName = indicator0
59 | }
60 |
61 | MODULE {
62 | name = ModuleControllableEmissive
63 | target = IndicatorLights/Meshes/squareLamp:2,3
64 | emissiveName = indicator1
65 | }
66 |
67 | //-------------------------------------------------------------------------
68 | // CONTROLLERS
69 | //-------------------------------------------------------------------------
70 |
71 | // Master switch that turns all the crew indicators on/off.
72 | MODULE {
73 | name = ModuleCrewIndicatorToggle
74 | toggleName = indicatorToggle
75 | }
76 |
77 | // Evaluates to true when research is happening.
78 | MODULE {
79 | name = ModuleConverterIndicator
80 | converterName = Research
81 | }
82 |
83 | // Indicator for slot 0.
84 | MODULE {
85 | name = ModuleCrewIndicator
86 | controllerName = crew0
87 | }
88 | MODULE {
89 | name = ModuleBooleanIndicator
90 | emissiveName = indicator0
91 | input = hasCrewEffect(ScienceSkill, 0)
92 | activeColor = if(ModuleConverterIndicator, pulsate(crew0, 600, 0.5), crew0)
93 | inactiveColor = blink(dim(crew0, 0.7), 150, $Off, 650)
94 | }
95 |
96 | // Indicator for slot 1.
97 | MODULE {
98 | name = ModuleCrewIndicator
99 | controllerName = crew1
100 | }
101 | MODULE {
102 | name = ModuleBooleanIndicator
103 | emissiveName = indicator1
104 | input = hasCrewEffect(ScienceSkill, 1)
105 | activeColor = if(ModuleConverterIndicator, pulsate(crew1, 600, 0.5), crew1)
106 | inactiveColor = blink(dim(crew1, 0.7), 150, $Off, 650)
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/files/Parts/crewable/mk2cockpit.cfg:
--------------------------------------------------------------------------------
1 | // Adds occupancy indicators to the Mk2 cockpit.
2 |
3 | @PART[mk2Cockpit_Standard]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Command/mk2CockpitStandard/model
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 1, 0.25, 0.5
23 | position = 0.7605, -0.9928, -0.44
24 | rotation = 0, 150, 0
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/squareLamp
30 | scale = 1, 0.25, 0.5
31 | position = 0.7605, -0.6728, -0.428
32 | rotation = 0, 150, 0
33 | }
34 |
35 | //-------------------------------------------------------------------------
36 | // CONTROLLABLE EMISSIVES
37 | //-------------------------------------------------------------------------
38 |
39 | MODULE {
40 | name = ModuleControllableEmissive
41 | target = IndicatorLights/Meshes/squareLamp:0
42 | emissiveName = indicator0
43 | }
44 |
45 | MODULE {
46 | name = ModuleControllableEmissive
47 | target = IndicatorLights/Meshes/squareLamp:1
48 | emissiveName = indicator1
49 | }
50 |
51 | //-------------------------------------------------------------------------
52 | // CONTROLLERS
53 | //-------------------------------------------------------------------------
54 |
55 | MODULE {
56 | name = ModuleCrewIndicatorToggle
57 | toggleName = indicatorToggle
58 | }
59 |
60 | MODULE {
61 | name = ModuleCrewIndicator
62 | controllerName = crewController0
63 | toggleName = indicatorToggle
64 | }
65 |
66 | MODULE {
67 | name = ModuleCrewIndicator
68 | controllerName = crewController1
69 | toggleName = indicatorToggle
70 | }
71 |
72 | MODULE
73 | {
74 | name = ModuleScienceAvailabilityIndicator
75 | controllerName = availability0
76 | experimentID = crewReport
77 | lowValueColor = crewController0
78 | mediumValueColor = highValueColor
79 | highValueColor = blink(lowValueColor, 200, $Off, 200)
80 | }
81 |
82 | MODULE
83 | {
84 | name = ModuleScienceAvailabilityIndicator
85 | controllerName = availability1
86 | experimentID = crewReport
87 | lowValueColor = crewController1
88 | mediumValueColor = highValueColor
89 | highValueColor = blink(lowValueColor, 200, $Off, 200)
90 | }
91 |
92 | MODULE {
93 | name = ModuleScienceDataIndicator
94 | experimentID = crewReport
95 | emissiveName = indicator0
96 | dataColor = crewController0
97 | emptyColor = availability0
98 | }
99 |
100 | MODULE {
101 | name = ModuleScienceDataIndicator
102 | experimentID = crewReport
103 | emissiveName = indicator1
104 | dataColor = crewController1
105 | emptyColor = availability1
106 | }
107 | }
--------------------------------------------------------------------------------
/files/Parts/crewable/mk2cockpitInline.cfg:
--------------------------------------------------------------------------------
1 | // Adds occupancy indicators to the Mk2 inline cockpit.
2 | // Thanks to Dominiquini in the KSP forums for supplying the config!
3 |
4 | @PART[mk2Cockpit_Inline]:FOR[IndicatorLights] {
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Command/mk2CockpitInline/model
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/nubbinLamp
22 | scale = 0.65, 0.65, 0.5
23 | position = 0, 0.551, -1.086
24 | rotation = -10, 180, 0
25 | }
26 |
27 | MODEL
28 | {
29 | model = IndicatorLights/Meshes/nubbinLamp
30 | scale = 0.65, 0.65, 0.5
31 | position = 0, 0.471, -1.101
32 | rotation = -5, 180, 0
33 | }
34 |
35 | //-------------------------------------------------------------------------
36 | // CONTROLLABLE EMISSIVES
37 | //-------------------------------------------------------------------------
38 | MODULE {
39 | name = ModuleControllableEmissive
40 | target = IndicatorLights/Meshes/nubbinLamp:0
41 | emissiveName = indicator0
42 | }
43 |
44 | MODULE {
45 | name = ModuleControllableEmissive
46 | target = IndicatorLights/Meshes/nubbinLamp:1
47 | emissiveName = indicator1
48 | }
49 |
50 | //-------------------------------------------------------------------------
51 | // CONTROLLERS
52 | //-------------------------------------------------------------------------
53 | MODULE {
54 | name = ModuleCrewIndicatorToggle
55 | toggleName = indicatorToggle
56 | }
57 |
58 | MODULE {
59 | name = ModuleCrewIndicator
60 | controllerName = crewController0
61 | toggleName = indicatorToggle
62 | }
63 |
64 | MODULE {
65 | name = ModuleCrewIndicator
66 | controllerName = crewController1
67 | toggleName = indicatorToggle
68 | }
69 |
70 | MODULE
71 | {
72 | name = ModuleScienceAvailabilityIndicator
73 | controllerName = availability0
74 | experimentID = crewReport
75 | lowValueColor = crewController0
76 | mediumValueColor = highValueColor
77 | highValueColor = blink(lowValueColor, 200, $Off, 200)
78 | }
79 |
80 | MODULE
81 | {
82 | name = ModuleScienceAvailabilityIndicator
83 | controllerName = availability1
84 | experimentID = crewReport
85 | lowValueColor = crewController1
86 | mediumValueColor = highValueColor
87 | highValueColor = blink(lowValueColor, 200, $Off, 200)
88 | }
89 |
90 | MODULE {
91 | name = ModuleScienceDataIndicator
92 | experimentID = crewReport
93 | emissiveName = indicator0
94 | dataColor = crewController0
95 | emptyColor = availability0
96 | }
97 |
98 | MODULE {
99 | name = ModuleScienceDataIndicator
100 | experimentID = crewReport
101 | emissiveName = indicator1
102 | dataColor = crewController1
103 | emptyColor = availability1
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/ModuleResourceIndicator.cs:
--------------------------------------------------------------------------------
1 | namespace IndicatorLights
2 | {
3 | ///
4 | /// Base class for modules that work with resources.
5 | ///
6 | abstract class ModuleResourceIndicator : ModuleEmissiveController
7 | {
8 | private PartResource resource = null;
9 |
10 | ///
11 | /// Determines which part is searched for the specified resource.
12 | ///
13 | [KSPField]
14 | public PartSearchStrategy searchStrategy = PartSearchStrategies.Default;
15 |
16 | ///
17 | /// The name of the resource which this controller tracks. If left null, the controller will
18 | /// pick the first resource it finds.
19 | ///
20 | [KSPField]
21 | public string resourceName = null;
22 |
23 | ///
24 | /// Called when the module is starting up.
25 | ///
26 | ///
27 | public override void OnStart(StartState state)
28 | {
29 | base.OnStart(state);
30 |
31 | resource = FindResource();
32 | if ((resource == null) && (searchStrategy == PartSearchStrategy.host))
33 | {
34 | Logging.Warn("ModuleResourceIndicator is inactive");
35 | return;
36 | }
37 | }
38 |
39 | protected PartResource Resource
40 | {
41 | get
42 | {
43 | if (searchStrategy != PartSearchStrategy.host)
44 | {
45 | Part sourcePart = (resource == null) ? null : resource.part;
46 | if (!searchStrategy.IsChoice(this, sourcePart))
47 | {
48 | resource = FindResource();
49 | }
50 | }
51 | return resource;
52 | }
53 | }
54 |
55 | ///
56 | /// Picks a resource to track.
57 | ///
58 | ///
59 | private PartResource FindResource()
60 | {
61 | Part sourcePart = searchStrategy.ChoosePart(this);
62 | if (sourcePart == null) return null;
63 | if ((sourcePart.Resources == null) || (sourcePart.Resources.Count == 0))
64 | {
65 | Logging.Warn(sourcePart.GetTitle() + " has no resources, can't track");
66 | return null;
67 | }
68 | if ((resourceName == null) || (resourceName.Length == 0))
69 | {
70 | if (sourcePart.Resources.Count > 1)
71 | {
72 | Logging.Log(sourcePart.GetTitle() + " has multiple resources; indicator is defaulting to " + sourcePart.Resources[0].resourceName);
73 | }
74 | return sourcePart.Resources[0];
75 | }
76 | for (int i = 0; i < sourcePart.Resources.Count; ++i)
77 | {
78 | PartResource resource = sourcePart.Resources[i];
79 | if (resourceName.Equals(resource.resourceName) && (resource.maxAmount > 0))
80 | {
81 | return resource;
82 | }
83 | }
84 | Logging.Warn("No resource '" + resourceName + "' found in " + sourcePart.GetTitle() + ", can't track");
85 | return null;
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/files/Parts/antennas/hg5.cfg:
--------------------------------------------------------------------------------
1 | // Adds an indicator to the HG-5 antenna.
2 |
3 | @PART[HighGainAntenna5_v2]:FOR[IndicatorLights] {
4 |
5 | //-------------------------------------------------------------------------
6 | // INDICATOR MESHES
7 | //-------------------------------------------------------------------------
8 |
9 | MODEL
10 | {
11 | model = IndicatorLights/Meshes/squareLamp2
12 | position = 0, 0.05, 0.1
13 | scale = 1.05, 0.7, 0.8
14 | rotation = 90, 0, 0
15 | }
16 |
17 |
18 | //-------------------------------------------------------------------------
19 | // CONTROLLABLE EMISSIVES
20 | //-------------------------------------------------------------------------
21 |
22 | MODULE {
23 | name = ModuleControllableEmissive
24 | target = IndicatorLights/Meshes/squareLamp2
25 | emissiveName = indicator
26 | }
27 |
28 |
29 | //-------------------------------------------------------------------------
30 | // CONTROLLERS
31 | //-------------------------------------------------------------------------
32 |
33 | MODULE {
34 | name = ModuleDataTransmitterIndicator
35 | emissiveName = indicator
36 | // Get really fancy with busy color. This module type exposes one static
37 | // field, dataRate. We'll use a random flicker for the animation (like
38 | // an old-time modem), and we'll plug the data rate both into the flicker
39 | // period (so higher-speed antennas flicker faster), and into the bias
40 | // (so higher-speed antennas spend a greater percentage of their time
41 | // in the "on" state rather than "off").
42 | //
43 | // We don't actually have to use the static syntax here (we could just
44 | // take the data rate for this antenna, do the math, and plug in the
45 | // literal numbers here). However, using the actual static expression
46 | // comes with a few benefits. First, it's more maintainable: we
47 | // can just use the same static expression for all the antennas, rather
48 | // than having to come up with a different expression with different math
49 | // for each one. Second, it's more explicit to anyone reading this just
50 | // *why* the number is what it is. Third, it's more robust: if Squad ever
51 | // tinkers with the data rates, or someone uses ModuleManager to tweak
52 | // them, this will automatically follow suit. Fourth, it's friendlier
53 | // to modders: if you have your own antenna and you want to set it up
54 | // for IndicatorLights compatibility, you can just copy the following
55 | // line verbatim and you'll get behavior that's consistent with what
56 | // IndicatorLights does with the stock antennas.
57 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
58 | }
59 | }
60 |
61 |
62 | //----------------------------------------------------------------------------
63 | // Legacy HG-5 model from older KSP versions
64 | @PART[HighGainAntenna5]:FOR[IndicatorLights] {
65 | MODEL
66 | {
67 | model = IndicatorLights/Meshes/squareLamp2
68 | position = -0.162, 0.036, -0.007
69 | scale = 1, 0.5, 1.15
70 | rotation = 0, 0, 90
71 | }
72 |
73 | MODULE {
74 | name = ModuleControllableEmissive
75 | target = IndicatorLights/Meshes/squareLamp2
76 | emissiveName = indicator
77 | }
78 |
79 | MODULE {
80 | name = ModuleDataTransmitterIndicator
81 | emissiveName = indicator
82 | busyColor = random($ToggleLED, $Off, divide(400, static(dataRate)), between(subtract(multiply(sqrt(static(dataRate)), 1.1), 2.3), -0.4, 0.5))
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/examples/ArbitraryFieldInputs.cfg:
--------------------------------------------------------------------------------
1 | // Demonstrate the use of field@module syntax.
2 | //
3 | // This example adds a light to the TR-2L Ruggedized Vehicular Wheel to show
4 | // its motor status. To do this, it works with three fields from ModuleWheelMotor:
5 | //
6 | // - motorEnabled ("is the motor turned on")
7 | // - motorInverted ("is the motor set up in reverse mode")
8 | // - driveOutput ("how much power is the motor currently putting out")
9 | //
10 | // The wheel is handy for demonstrating the usefulness of this syntax because
11 | // there aren't any IndicatorLights controllers that are specifically designed
12 | // to work with wheels. Therefore, to work with fields such as the above requires
13 | // the ability to target arbitrary fields, which is what the field@module syntax
14 | // is all about. Search this file for the "@" character to see how it's used.
15 |
16 |
17 | @PART[wheelMed] {
18 | @description ^= :(.)$:$0 Example wheel has indicator light showing motor status.:
19 |
20 | // We have to re-specify the model for the stock part, because this is
21 | // an older part that uses the "mesh =" syntax in its .cfg file instead
22 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
23 | // multiple models as part of the same part, which would prevent this mod
24 | // from adding meshes for the indicator lights.
25 | MODEL
26 | {
27 | model = Squad/Parts/Wheel/roverWheelTR-2L/model
28 | }
29 |
30 |
31 | //-------------------------------------------------------------------------
32 | // INDICATOR MESHES
33 | //-------------------------------------------------------------------------
34 |
35 | MODEL
36 | {
37 | model = IndicatorLights/Meshes/squareLamp2
38 | position = -0.194, 0.16, 0
39 | }
40 |
41 |
42 | //-------------------------------------------------------------------------
43 | // CONTROLLABLE EMISSIVES
44 | //-------------------------------------------------------------------------
45 |
46 | MODULE {
47 | name = ModuleControllableEmissive
48 | target = IndicatorLights/Meshes/squareLamp2
49 | emissiveName = indicator
50 | }
51 |
52 |
53 | //-------------------------------------------------------------------------
54 | // CONTROLLERS
55 | //-------------------------------------------------------------------------
56 |
57 | // A toggle that's on when the motor's active, off when it's not. When it's
58 | // on, emit green if it's in "normal" mode, red if the motor is inverted.
59 | // If motor output is under 60%, it's displayed dim.
60 | MODULE {
61 | name = ModuleBooleanIndicator
62 | controllerName = motorStatus
63 | // The input (i.e. deciding on versus off) is based on whether the
64 | // motor is enabled.
65 | input = motorEnabled@ModuleWheelMotor
66 | // When it's enabled, the color will be green or red depending on whether
67 | // it's in "forward" or "reverse" mode.
68 | activeColor = if(motorInverted@ModuleWheelMotor, #FF0000, #00FF00)
69 | // When the motor is not enabled, the light is simply off.
70 | inactiveColor = $Off
71 | }
72 |
73 | // Take the output of the toggles above, then adjust the brightness based
74 | // on the motor's drive output.
75 | MODULE {
76 | name = ModuleBooleanIndicator
77 | controllerName = motorPower
78 | input = motorStatus
79 | emissiveName = indicator
80 | // If the drive output of the motor is below 30%, display at half brightness.
81 | // Otherwise, display at full brightness.
82 | activeColor = if(lt(driveOutput@ModuleWheelMotor, 30), dim(motorStatus, 0.5), motorStatus)
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/files/Parts/batteries/Z4KIndicator.cfg:
--------------------------------------------------------------------------------
1 | // Adds LED indicators to the large, 4000 EC battery.
2 |
3 | @PART[batteryBankLarge]:FOR[IndicatorLights] {
4 | @description ^= :(.)$:$0 New, improved model now has status lights!:
5 |
6 | // We have to re-specify the model for the stock part, because this is
7 | // an older part that uses the "mesh =" syntax in its .cfg file instead
8 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
9 | // multiple models as part of the same part, which would prevent this mod
10 | // from adding meshes for the indicator lights.
11 | MODEL
12 | {
13 | model = Squad/Parts/Electrical/z-4kBattery/model
14 | }
15 |
16 | //-------------------------------------------------------------------------
17 | // INDICATOR MESHES
18 | //-------------------------------------------------------------------------
19 |
20 | MODEL
21 | {
22 | model = IndicatorLights/Meshes/squareLamp
23 | scale = 0.8, 0.8, 1
24 | position = -1.082, -0.02, 0.625
25 | rotation = 0, -60, 0
26 | }
27 |
28 | MODEL
29 | {
30 | model = IndicatorLights/Meshes/squareLamp
31 | scale = 0.8, 0.8, 1
32 | position = 1.082, -0.02, -0.625
33 | rotation = 0, 120, 0
34 | }
35 |
36 | MODEL
37 | {
38 | model = IndicatorLights/Meshes/squareLamp
39 | scale = 0.8, 0.8, 1
40 | position = 1.082, -0.02, 0.625
41 | rotation = 0, 60, 0
42 | }
43 |
44 | MODEL
45 | {
46 | model = IndicatorLights/Meshes/squareLamp
47 | scale = 0.79, 0.8, 1
48 | position = -1.082, -0.02, -0.625
49 | rotation = 0, 240, 0
50 | }
51 |
52 | // This one covers up an apparent (dummy) green-LED "light" that's present
53 | // on the stock model, and can confuse the player by appearing to be an
54 | // indicator when it isn't.
55 | MODEL
56 | {
57 | model = IndicatorLights/Meshes/squareLamp
58 | scale = 1.21, 0.62, 0.1
59 | position = -0.08, 0.016, -1.177
60 | rotation = 0, 180, 0
61 | }
62 |
63 |
64 | //-------------------------------------------------------------------------
65 | // CONTROLLABLE EMISSIVES
66 | //-------------------------------------------------------------------------
67 |
68 | MODULE {
69 | name = ModuleControllableEmissive
70 | target = IndicatorLights/Meshes/squareLamp:0,1,2,3
71 | emissiveName = indicator
72 | }
73 |
74 | MODULE {
75 | name = ModuleControllableEmissive
76 | target = IndicatorLights/Meshes/squareLamp:4
77 | emissiveName = patch
78 | }
79 |
80 | //-------------------------------------------------------------------------
81 | // CONTROLLERS
82 | //-------------------------------------------------------------------------
83 |
84 | MODULE {
85 | name = ModuleResourceLevelIndicator
86 | controllerName = mainResourceLevel
87 | }
88 |
89 | MODULE {
90 | name = ModuleResourceEnabledIndicator
91 | enabledColor = mainResourceLevel
92 | disabledColor = blink(ModuleResourceLevelIndicator, 900, $Off, 300)
93 | emissiveName = indicator
94 | }
95 |
96 | // This is for the patch that covers up the "dummy" LED on the stock model.
97 | // It doesn't really fit with the design of the rest of the indicators
98 | // we're adding here, so it'll be off most of the time. Light it up dimly
99 | // when we're out of juice.
100 | MODULE {
101 | name = ModuleResourceLevelIndicator
102 | emissiveName = patch
103 | highColor = $Off
104 | mediumColor = $Off
105 | lowColor = $Off
106 | criticalColor = $Off
107 | emptyColor = dim($LowResource, 0.5)
108 | }
109 | }
--------------------------------------------------------------------------------
/files/Parts/obsolete/mk1pod.cfg:
--------------------------------------------------------------------------------
1 | // Adds an occupancy indicator to the Mk1 command pod.
2 |
3 | @PART[mk1pod]:FOR[IndicatorLights] {
4 |
5 | // We have to re-specify the model for the stock part, because this is
6 | // an older part that uses the "mesh =" syntax in its .cfg file instead
7 | // of the newer "MODEL" syntax. The "mesh =" syntax doesn't allow having
8 | // multiple models as part of the same part, which would prevent this mod
9 | // from adding meshes for the indicator lights.
10 | MODEL
11 | {
12 | model = Squad/Parts/Command/mk1pod/model
13 | }
14 |
15 | //-------------------------------------------------------------------------
16 | // INDICATOR MESHES
17 | //-------------------------------------------------------------------------
18 |
19 | MODEL
20 | {
21 | model = IndicatorLights/Meshes/squareLamp
22 | scale = 1, 0.25, 0.5
23 | position = 0, 0, -0.5138
24 | rotation = -160, 0, 0
25 | }
26 |
27 | //-------------------------------------------------------------------------
28 | // CONTROLLABLE EMISSIVES
29 | //-------------------------------------------------------------------------
30 |
31 | MODULE {
32 | name = ModuleControllableEmissive
33 | target = IndicatorLights/Meshes/squareLamp
34 | emissiveName = indicator
35 | }
36 |
37 | //-------------------------------------------------------------------------
38 | // CONTROLLERS
39 | //-------------------------------------------------------------------------
40 |
41 | MODULE {
42 | name = ModuleCrewIndicatorToggle
43 | toggleName = indicatorToggle
44 | }
45 |
46 | MODULE {
47 | name = ModuleCrewIndicator
48 | toggleName = indicatorToggle
49 | }
50 |
51 | MODULE
52 | {
53 | name = ModuleScienceAvailabilityIndicator
54 | experimentID = crewReport
55 | lowValueColor = ModuleCrewIndicator
56 | mediumValueColor = highValueColor
57 | highValueColor = blink(lowValueColor, 200, $Off, 200)
58 | }
59 |
60 | MODULE {
61 | name = ModuleScienceDataIndicator
62 | experimentID = crewReport
63 | emissiveName = indicator
64 | dataColor = ModuleCrewIndicator
65 | emptyColor = ModuleScienceAvailabilityIndicator
66 | }
67 |
68 | //-------------------------------------------------------------------------
69 | // TWEAKS
70 | //-------------------------------------------------------------------------
71 |
72 | // This pod uses a ModuleColorChanger to handle its cabin lights, set up
73 | // so that by default it takes control of *all* emissives on the part.
74 | // Need to tell it not to tinker with the meshes that we're adding here;
75 | // otherwise, the crew indicator will just turn on and off with the cabin
76 | // lights instead of actually working as a crew indicator.
77 | @MODULE[ModuleColorChanger] {
78 | excludedRenderer = IndicatorLights/Meshes/squareLamp(Clone)
79 |
80 | // As long as we're tinkering here anyay... let's fix a 1.2 bug. :-)
81 | // ModuleColorChanger breaks the thermal overlay for the crewed parts
82 | // that use it for cabin lights. We can fix this by telling it
83 | // to ignore various meshes *other* than the window. Can remove this
84 | // hack once Squad gets around to fixing ModuleColorChanger. In the
85 | // meantime, this makes it better, and I can enjoy waiting to see whether
86 | // anyone actually notices!
87 | excludedRenderer = capsule
88 | excludedRenderer = hatch
89 | excludedRenderer = flagTransform
90 | excludedRenderer = rung
91 | // ...Can remove the hack once Squad fixes this part's config so it doesn't
92 | // break the thermal overlay.
93 | }
94 | }
95 |
--------------------------------------------------------------------------------