1
0
mirror of synced 2024-11-22 10:03:51 +00:00

Added placeholders for all 1.6 functions

Implemented most of the systems functions
This commit is contained in:
Mark van Renswoude 2017-06-06 23:59:54 +02:00
parent 897ba9310e
commit b597235874
15 changed files with 321 additions and 101 deletions

View File

@ -59,6 +59,9 @@ Registers a button function.
| **default**: string | **default**: string
| The default color and/or animation assigned to the state when it is first selected. See :ref:`ref-ledcolor` for a list of valid values. | The default color and/or animation assigned to the state when it is first selected. See :ref:`ref-ledcolor` for a list of valid values.
| |
| **order**: number (optional)
| Specifies the order in which the state is shown in the button function selection screen. If not specified, defaults to 0. States with an equal order are sorted alphabetically.
|
| **setupCallback**: function | **setupCallback**: function
| A Lua function which is called when the button function is configured. Please note that if a button function is linked to multiple G940 throttle buttons, setupCallback is called multiple times, so be careful with variables which are outside of the setupCallback's scope (global or script-local)! | A Lua function which is called when the button function is configured. Please note that if a button function is linked to multiple G940 throttle buttons, setupCallback is called multiple times, so be careful with variables which are outside of the setupCallback's scope (global or script-local)!
| |
@ -129,9 +132,12 @@ Registers a Lua function to be called when the specified SimConnect variable(s)
| **variable**: string | **variable**: string
| The name of the variable as described in `Simulation variables <https://msdn.microsoft.com/en-us/library/cc526981.aspx>`_. | The name of the variable as described in `Simulation variables <https://msdn.microsoft.com/en-us/library/cc526981.aspx>`_.
| |
| **data**: string | **type**: string
| One of the :ref:`ref-simconnectdatatype` values. | One of the :ref:`ref-simconnectdatatype` values.
| |
| **units**: string
| If relevant to the variable, one of the `Units of Measurement <https://msdn.microsoft.com/en-us/library/cc526981.aspx#UnitsofMeasurement>`_ supported by SimConnect. For example, 'percent'. If type is SimConnectDataType.Bool, this will be automatically set to 'bool'.
|
| **variablesChangedCallback**: function | **variablesChangedCallback**: function
| A Lua function which is called when the variable's value changes. It receives 2 parameters: 'context' and 'data'. The data parameter is a Lua table where each key corresponds to a variable defined in the 'variables' parameter and it's value is the current value of the simulation variable. | A Lua function which is called when the variable's value changes. It receives 2 parameters: 'context' and 'data'. The data parameter is a Lua table where each key corresponds to a variable defined in the 'variables' parameter and it's value is the current value of the simulation variable.
| |

View File

@ -1,7 +1,7 @@
object MainForm: TMainForm object MainForm: TMainForm
Left = 0 Left = 0
Top = 0 Top = 0
ActiveControl = cbTrayIcon ActiveControl = cmbProfiles
BorderIcons = [biSystemMenu, biMinimize] BorderIcons = [biSystemMenu, biMinimize]
BorderStyle = bsSingle BorderStyle = bsSingle
Caption = 'G940 LED Control' Caption = 'G940 LED Control'
@ -30,7 +30,7 @@ object MainForm: TMainForm
Margins.Top = 8 Margins.Top = 8
Margins.Right = 8 Margins.Right = 8
Margins.Bottom = 8 Margins.Bottom = 8
ActivePage = tsConfiguration ActivePage = tsButtons
Align = alClient Align = alClient
TabOrder = 0 TabOrder = 0
object tsButtons: TTabSheet object tsButtons: TTabSheet
@ -529,10 +529,6 @@ object MainForm: TMainForm
object tsAbout: TTabSheet object tsAbout: TTabSheet
Caption = 'About' Caption = 'About'
ImageIndex = 1 ImageIndex = 1
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 0
ExplicitHeight = 0
object lblVersionCaption: TLabel object lblVersionCaption: TLabel
Left = 16 Left = 16
Top = 67 Top = 67

View File

@ -53,14 +53,17 @@ var
begin begin
isRestarting := FindCmdLineSwitch('restart'); isRestarting := FindCmdLineSwitch('restart');
while not SingleInstance('{67D1802F-2AB8-40B9-ADD7-14C9D36903C8}', False, False) do if not FindCmdLineSwitch('multiinstance') then
begin begin
Instance.Close; while not SingleInstance('{67D1802F-2AB8-40B9-ADD7-14C9D36903C8}', False, False) do
begin
Instance.Close;
if not isRestarting then if not isRestarting then
exit; exit;
Sleep(1000); Sleep(1000);
end;
end; end;
Application.Initialize; Application.Initialize;

View File

@ -97,7 +97,7 @@
<DCC_UNIT_PLATFORM>False</DCC_UNIT_PLATFORM> <DCC_UNIT_PLATFORM>False</DCC_UNIT_PLATFORM>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''"> <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<Debugger_RunParams>/restart</Debugger_RunParams> <Debugger_RunParams>/multiinstance</Debugger_RunParams>
<VerInfo_IncludeVerInfo>false</VerInfo_IncludeVerInfo> <VerInfo_IncludeVerInfo>false</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.1.3.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=0.2;Comments=</VerInfo_Keys> <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.1.3.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=0.2;Comments=</VerInfo_Keys>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File> <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>

View File

@ -1,15 +1,23 @@
local strings = require './lib/strings' local strings = require './lib/strings'
-- Autopilot master
-- Autopilot altitude
-- Autopilot approach
-- Autopilot backcourse
-- Autopilot heading
-- Autopilot nav
-- Autopilot airspeed
RegisterFunction( RegisterFunction(
{ {
uid = 'autoPilotAirspeed', uid = 'autoPilotAirspeed',
category = strings.Category.FSX.AutoPilot, category = strings.Category.FSX.AutoPilot,
displayName = 'Autopilot airspeed', displayName = 'Autopilot airspeed',
states = { states = {
on = { displayName = 'On', default = LEDColor.Green }, notAvailable = { displayName = 'Not available', default = LEDColor.Off, order = 1 },
off = { displayName = 'Off', default = LEDColor.Red }, on = { displayName = 'On', default = LEDColor.Green, order = 2 },
notAvailable = { displayName = 'Not available', default = LEDColor.Off } off = { displayName = 'Off', default = LEDColor.Red, order = 3 }
} }
}, },
function(context) function(context)

View File

@ -0,0 +1,6 @@
-- Flaps
-- Flaps (handle position)
-- Flaps (handle position - percentage)
-- Spoilers
-- Auto-spoilers armed
-- Water rudder

View File

@ -0,0 +1,3 @@
-- Carb heat / engine anti-ice
-- Engine
-- Throttle

View File

@ -0,0 +1,2 @@
-- Pitot heat (on / off only)
-- Pitot heat (including warnings)

View File

@ -0,0 +1,49 @@
local basefunctions = {}
-- Required keys for info:
-- uid
-- category
-- displayName
-- variable (SimConnect boolean-compatible variable name)
--
-- Optional keys:
-- inverted (Off is Green instead of Red)
basefunctions.RegisterOnOffFunction = function(info)
if info.inverted then
onOffStates = {
on = { displayName = 'On', default = LEDColor.Green, order = 1 },
off = { displayName = 'Off', default = LEDColor.Red, order = 2 }
}
else
onOffStates = {
on = { displayName = 'On', default = LEDColor.Red, order = 1 },
off = { displayName = 'Off', default = LEDColor.Green, order = 2 }
}
end
RegisterFunction(
{
uid = info.uid,
category = info.category,
displayName = info.displayName,
states = onOffStates
},
function(context)
SetState(context, 'on')
OnSimConnect(context,
{
value = { variable = info.variable, type = SimConnectDataType.Bool }
},
function(context, data)
if data.value then
SetState(context, 'on')
else
SetState(context, 'off')
end
end)
end
)
end
return basefunctions

View File

@ -0,0 +1,8 @@
-- Beacon lights
-- Instrument lights
-- Landing lights
-- Nav lights
-- Recognition lights
-- Strobe lights
-- Taxi lights
-- All lights

View File

@ -1,14 +1,16 @@
local strings = require './lib/strings' local strings = require './lib/strings'
-- ATC panel
RegisterFunction( RegisterFunction(
{ {
uid = 'atcVisiblity', uid = 'atcVisiblity',
category = strings.Category.FSX.Panels, category = strings.Category.FSX.Panels,
displayName = 'ATC Visibility', displayName = 'ATC panel',
states = { states = {
hidden = { displayName = 'Hidden', default = LEDColor.Green }, hidden = { displayName = 'Hidden', default = LEDColor.Green, order = 1 },
visible = { displayName = 'Visible', default = LEDColor.FlashingAmberNormal }, visible = { displayName = 'Visible', default = LEDColor.FlashingAmberNormal, order = 2 },
} }
}, },
function(context) function(context)

View File

@ -0,0 +1 @@
-- Avionics master

View File

@ -0,0 +1,173 @@
local basefunctions = require './lib/basefunctions'
local strings = require './lib/strings'
-- Battery master
basefunctions.RegisterOnOffFunction({
category = strings.Category.FSX.Systems,
uid = 'batteryMaster',
displayName = 'Battery Master',
variable = 'ELECTRICAL MASTER BATTERY'
})
-- De-ice
basefunctions.RegisterOnOffFunction({
category = strings.Category.FSX.Systems,
uid = 'structuralDeIce',
displayName = "De-ice",
variable = 'STRUCTURAL DEICE SWITCH'
})
-- Exit door
RegisterFunction(
{
uid = 'exitDoor',
category = strings.Category.FSX.Systems,
displayName = 'Exit door',
states = {
closed = { displayName = 'Closed', default = LEDColor.Green, order = 1 },
between = { displayName = 'Opening / closing', default = LEDColor.Amber, order = 2 },
open = { displayName = 'Open', default = LEDColor.Red, order = 3 }
}
},
function(context)
SetState(context, 'closed')
OnSimConnect(context,
{
canopyOpen = { variable = 'CANOPY OPEN', type = SimConnectDataType.Float64, units = 'percent' }
},
function(context, data)
if data.canopyOpen >= 0 and data.canopyOpen <= 5 then
SetState(context, 'closed')
elseif data.canopyOpen >= 95 and data.canopyOpen <= 100 then
SetState(context, 'open')
else
SetState(context, 'between')
end
end)
end
)
-- Landing gears
local function registerGearFunction(functionUid, functionDisplayName, variableName, isFloat)
RegisterFunction(
{
uid = functionUid,
category = strings.Category.FSX.Systems,
displayName = functionDisplayName,
states = {
notRetractable = { displayName = 'Not retractable', default = LEDColor.Off, order = 1 },
retracted = { displayName = 'Retracted', default = LEDColor.Red, order = 2 },
between = { displayName = 'Extending / retracting', default = LEDColor.Amber, order = 3 },
extended = { displayName = 'Extended', default = LEDColor.Green, order = 4 },
speedExceeded = { displayName = 'Speed exceeded', default = LEDColor.FlashingAmberNormal, order = 5 },
damageBySpeed = { displayName = 'Damage by speed', default = LEDColor.FlashingRedFast, order = 6 }
}
},
function(context)
SetState(context, 'notRetractable')
OnSimConnect(context,
{
isGearRetractable = { variable = 'IS GEAR RETRACTABLE', type = SimConnectDataType.Bool },
percentageExtended = { variable = variableName, type = SimConnectDataType.Float64, units = 'percent' },
damageBySpeed = { variable = 'GEAR DAMAGE BY SPEED', type = SimConnectDataType.Bool },
speedExceeded = { variable = 'GEAR SPEED EXCEEDED', type = SimConnectDataType.Bool },
},
function(context, data)
if data.damageBySpeed then
SetState(context, 'damageBySpeed')
elseif data.speedExceeded then
SetState(context, 'speedExceeded')
elseif data.isGearRetractable then
local extended = data.percentageExtended
if isFloat then
extended = extended * 100
end
extended = math.floor(extended)
if extended == 0 then
SetState(context, 'retracted')
elseif extended >= 95 and extended <= 100 then
SetState(context, 'extended')
else
SetState(context, 'between')
end
else
SetState(context, 'notRetractable')
end
end)
end
)
end
registerGearFunction('gear', 'Landing gear', 'GEAR TOTAL PCT EXTENDED', true)
registerGearFunction('leftGear', 'Left main landing gear', 'GEAR LEFT POSITION', false)
registerGearFunction('rightGear', 'Right main landing gear', 'GEAR RIGHT POSITION', false)
registerGearFunction('centerGear', 'Nose landing gear', 'GEAR CENTER POSITION', false)
registerGearFunction('tailGear', 'Tail landing gear', 'GEAR TAIL POSITION', false)
-- Parking brake
basefunctions.RegisterOnOffFunction({
category = strings.Category.FSX.Systems,
uid = 'parkingBrake',
displayName = 'Parking brake',
variable = 'BRAKE PARKING INDICATOR'
})
-- Auto brake
RegisterFunction(
{
uid = 'autoBrake',
category = strings.Category.FSX.Systems,
displayName = 'Auto brake',
states = {
['0'] = { displayName = 'Off / not available', default = LEDColor.Green, order = 1 },
['1'] = { displayName = '1', default = LEDColor.Amber, order = 2 },
['2'] = { displayName = '2', default = LEDColor.Amber, order = 3 },
['3'] = { displayName = '3', default = LEDColor.Amber, order = 4 },
['4'] = { displayName = '4', default = LEDColor.Red, order = 5 }
}
},
function(context)
SetState(context, '0')
OnSimConnect(context,
{
switch = { variable = 'AUTO BRAKE SWITCH CB', type = SimConnectDataType.Int32, units = 'number' }
},
function(context, data)
local switch = 4
if data.switch >= 0 and data.switch <= 4 then
switch = data.switch
end
SetState(context, tostring(switch))
end)
end
)
-- Pressurization dump switch
basefunctions.RegisterOnOffFunction({
category = strings.Category.FSX.Systems,
uid = 'pressurizationDumpSwitch',
displayName = 'Pressurization dump switch',
variable = 'PRESSURIZATION DUMP SWITCH'
})
-- Tail hook
-- Tail wheel lock
-- Float (left)
-- Float (right)
-- Fuel level

View File

@ -176,75 +176,6 @@ begin
end; end;
(*
procedure TFSXLEDFunctionProvider.RegisterFunctions;
begin
inherited RegisterFunctions;
{ Systems }
RegisterFunction(TFSXBatteryMasterFunction.Create( Self, FSXFunctionDisplayNameBatteryMaster, FSXFunctionUIDBatteryMaster));
RegisterFunction(TFSXDeIceFunction.Create( Self, FSXFunctionDisplayNameDeIce, FSXFunctionUIDDeIce));
RegisterFunction(TFSXExitDoorFunction.Create( Self, FSXFunctionDisplayNameExitDoor, FSXFunctionUIDExitDoor));
RegisterFunction(TFSXGearFunction.Create( Self, FSXFunctionDisplayNameGear, FSXFunctionUIDGear));
RegisterFunction(TFSXLeftGearFunction.Create( Self, FSXFunctionDisplayNameLeftGear, FSXFunctionUIDLeftGear));
RegisterFunction(TFSXRightGearFunction.Create( Self, FSXFunctionDisplayNameRightGear, FSXFunctionUIDRightGear));
RegisterFunction(TFSXCenterGearFunction.Create( Self, FSXFunctionDisplayNameCenterGear, FSXFunctionUIDCenterGear));
RegisterFunction(TFSXTailGearFunction.Create( Self, FSXFunctionDisplayNameTailGear, FSXFunctionUIDTailGear));
RegisterFunction(TFSXParkingBrakeFunction.Create( Self, FSXFunctionDisplayNameParkingBrake, FSXFunctionUIDParkingBrake));
RegisterFunction(TFSXAutoBrakeFunction.Create( Self, FSXFunctionDisplayNameAutoBrake, FSXFunctionUIDAutoBrake));
RegisterFunction(TFSXPressDumpSwitchFunction.Create( Self, FSXFunctionDisplayNamePressDumpSwitch, FSXFunctionUIDPressDumpSwitch));
RegisterFunction(TFSXTailHookFunction.Create( Self, FSXFunctionDisplayNameTailHook, FSXFunctionUIDTailHook));
RegisterFunction(TFSXTailWheelLockFunction.Create( Self, FSXFunctionDisplayNameTailWheelLock, FSXFunctionUIDTailWheelLock));
RegisterFunction(TFSXFloatLeftFunction.Create( Self, FSXFunctionDisplayNameFloatLeft, FSXFunctionUIDFloatLeft));
RegisterFunction(TFSXFloatRightFunction.Create( Self, FSXFunctionDisplayNameFloatRight, FSXFunctionUIDFloatRight));
{ Instruments }
RegisterFunction(TFSXPitotOnOffFunction.Create( Self, FSXFunctionDisplayNamePitotOnOff, FSXFunctionUIDPitotOnOff));
RegisterFunction(TFSXPitotWarningFunction.Create( Self, FSXFunctionDisplayNamePitotWarning, FSXFunctionUIDPitotWarning));
{ Engines }
RegisterFunction(TFSXEngineAntiIceFunction.Create( Self, FSXFunctionDisplayNameEngineAntiIce, FSXFunctionUIDEngineAntiIce));
RegisterFunction(TFSXEngineFunction.Create( Self, FSXFunctionDisplayNameEngine, FSXFunctionUIDEngine));
RegisterFunction(TFSXThrottleFunction.Create( Self, FSXFunctionDisplayNameThrottle, FSXFunctionUIDThrottle));
{ Control surfaces }
RegisterFunction(TFSXFlapsFunction.Create( Self, FSXFunctionDisplayNameFlaps, FSXFunctionUIDFlaps));
RegisterFunction(TFSXFlapsHandleIndexFunction.Create( Self, FSXFunctionDisplayNameFlapsHandleIndex, FSXFunctionUIDFlapsHandleIndex));
RegisterFunction(TFSXFlapsHandlePercentageFunction.Create(Self, FSXFunctionDisplayNameFlapsHandlePercentage, FSXFunctionUIDFlapsHandlePercentage));
RegisterFunction(TFSXSpoilersFunction.Create( Self, FSXFunctionDisplayNameSpoilers, FSXFunctionUIDSpoilers));
RegisterFunction(TFSXSpoilersArmedFunction.Create( Self, FSXFunctionDisplayNameSpoilersArmed, FSXFunctionUIDSpoilersArmed));
RegisterFunction(TFSXWaterRudderFunction.Create( Self, FSXFunctionDisplayNameWaterRudder, FSXFunctionUIDWaterRudder));
{ Lights }
RegisterFunction(TFSXBeaconLightsFunction.Create( Self, FSXFunctionDisplayNameBeaconLights, FSXFunctionUIDBeaconLights));
RegisterFunction(TFSXInstrumentLightsFunction.Create( Self, FSXFunctionDisplayNameInstrumentLights, FSXFunctionUIDInstrumentLights));
RegisterFunction(TFSXLandingLightsFunction.Create( Self, FSXFunctionDisplayNameLandingLights, FSXFunctionUIDLandingLights));
RegisterFunction(TFSXNavLightsFunction.Create( Self, FSXFunctionDisplayNameNavLights, FSXFunctionUIDNavLights));
RegisterFunction(TFSXRecognitionLightsFunction.Create( Self, FSXFunctionDisplayNameRecognitionLights, FSXFunctionUIDRecognitionLights));
RegisterFunction(TFSXStrobeLightsFunction.Create( Self, FSXFunctionDisplayNameStrobeLights, FSXFunctionUIDStrobeLights));
RegisterFunction(TFSXTaxiLightsFunction.Create( Self, FSXFunctionDisplayNameTaxiLights, FSXFunctionUIDTaxiLights));
RegisterFunction(TFSXAllLightsFunction.Create( Self, FSXFunctionDisplayNameAllLights, FSXFunctionUIDAllLights));
{ Autopilot }
RegisterFunction(TFSXAutoPilotFunction.Create( Self, FSXFunctionDisplayNameAutoPilot, FSXFunctionUIDAutoPilot));
RegisterFunction(TFSXAutoPilotAltitudeFunction.Create( Self, FSXFunctionDisplayNameAutoPilotAltitude, FSXFunctionUIDAutoPilotAltitude));
RegisterFunction(TFSXAutoPilotApproachFunction.Create( Self, FSXFunctionDisplayNameAutoPilotApproach, FSXFunctionUIDAutoPilotApproach));
RegisterFunction(TFSXAutoPilotBackcourseFunction.Create( Self, FSXFunctionDisplayNameAutoPilotBackcourse, FSXFunctionUIDAutoPilotBackcourse));
RegisterFunction(TFSXAutoPilotHeadingFunction.Create( Self, FSXFunctionDisplayNameAutoPilotHeading, FSXFunctionUIDAutoPilotHeading));
RegisterFunction(TFSXAutoPilotNavFunction.Create( Self, FSXFunctionDisplayNameAutoPilotNav, FSXFunctionUIDAutoPilotNav));
RegisterFunction(TFSXAutoPilotAirspeedFunction.Create( Self, FSXFunctionDisplayNameAutoPilotAirspeed, FSXFunctionUIDAutoPilotAirspeed));
{ Radios }
RegisterFunction(TFSXAvionicsMasterFunction.Create( Self, FSXFunctionDisplayNameAvionicsMaster, FSXFunctionUIDAvionicsMaster));
{ Fuel }
RegisterFunction(TFSXFuelFunction.Create( Self, FSXFunctionDisplayNameFuel, FSXFunctionUIDFuel));
{ ATC }
RegisterFunction(TFSXATCVisibilityFunction.Create(FSXProviderUID));
end;
*)
function TFSXLEDFunctionProvider.CreateLuaLEDFunction(AInfo: ILuaTable; AOnSetup: ILuaFunction): TCustomLuaLEDFunction; function TFSXLEDFunctionProvider.CreateLuaLEDFunction(AInfo: ILuaTable; AOnSetup: ILuaFunction): TCustomLuaLEDFunction;
begin begin
Result := TFSXLEDFunction.Create(Self, AInfo, AOnSetup); Result := TFSXLEDFunction.Create(Self, AInfo, AOnSetup);

View File

@ -108,6 +108,8 @@ implementation
uses uses
System.Classes, System.Classes,
System.IOUtils, System.IOUtils,
System.Generics.Defaults,
System.Math,
System.StrUtils, System.StrUtils,
Winapi.Windows, Winapi.Windows,
@ -557,32 +559,62 @@ end;
procedure TCustomLuaLEDFunction.RegisterStates; procedure TCustomLuaLEDFunction.RegisterStates;
type
TOrderedLEDState = record
Order: Integer;
State: ILEDState;
end;
var var
state: TLuaKeyValuePair; states: TList<TOrderedLEDState>;
scriptState: TLuaKeyValuePair;
displayName: string; displayName: string;
defaultColor: TLEDColor; defaultColor: TLEDColor;
info: ILuaTable; info: ILuaTable;
state: TOrderedLEDState;
begin begin
if not Assigned(ScriptStates) then if not Assigned(ScriptStates) then
exit; exit;
for state in ScriptStates do states := TList<TOrderedLEDState>.Create;
begin try
displayName := state.Key.AsString; for scriptState in ScriptStates do
defaultColor := lcOff;
if state.Value.VariableType = VariableTable then
begin begin
info := state.Value.AsTable; state.Order := 0;
if info.HasValue('displayName') then
displayName := info.GetValue('displayName').AsString;
if info.HasValue('default') then displayName := scriptState.Key.AsString;
defaultColor := GetLEDColor(info.GetValue('default').AsString); defaultColor := lcOff;
if scriptState.Value.VariableType = VariableTable then
begin
info := scriptState.Value.AsTable;
if info.HasValue('displayName') then
displayName := info.GetValue('displayName').AsString;
if info.HasValue('default') then
defaultColor := GetLEDColor(info.GetValue('default').AsString);
if info.HasValue('order') then
state.Order := info.GetValue('order').AsInteger;
end;
state.State := TLEDState.Create(scriptState.Key.AsString, displayName, defaultColor);
states.Add(state)
end; end;
RegisterState(TLEDState.Create(state.Key.AsString, displayName, defaultColor)); states.Sort(TDelegatedComparer<TOrderedLEDState>.Create(
function(const Left, Right: TOrderedLEDState): Integer
begin
Result := CompareValue(Left.Order, Right.Order);
if Result = 0 then
Result := CompareText(Left.State.GetDisplayName, Right.State.GetDisplayName);
end));
for state in states do
RegisterState(state.State);
finally
FreeAndNil(states);
end; end;
end; end;