-
Notifications
You must be signed in to change notification settings - Fork 168
MCM State Options
State options have been added in MCM 2.0 to provide a better method of organizing the event handler code.
However, due to the fact that mod authors are already used to the classic API, or made huge menus that would take a long time to convert, state options will not replace the default API. But if you are interested in writing better code, or if you're facing scalability issues, consider using them.
The rest of this document assumes that you are already familiar with the basic MCM principles.
As explained in the other guides, the original method of identifying single options is by option ID. A generic example:
int aOID
int bOID
...
int zOID
event OnPageReset(string page)
aOID = AddToggleOption("A", true)
bOID = AddToggleOption("B", true)
...
zOID = AddToggleOption("Z", true)
endEvent
event OnOptionSelect(int option)
if (option == aOID)
SetTextOptionValue(aOID, false)
elseIf (option == bOID)
...
elseIf (option == zOID)
SetTextOptionValue(zOID, false)
endIf
endEvent
event OnOptionDefault(int option)
if (option == aOID)
SetTextOptionValue(aOID, true)
elseIf (option == bOID)
...
elseIf (option == zOID)
SetTextOptionValue(zOID, false)
endIf
endEvent
event OnOptionHighlight(int option)
if (option == aOID)
SetInfoText("Option A bla")
elseIf (option == bOID)
...
elseIf (option == zOID)
SetInfoText("Option Z bla")
endIf
endEvent
The actual handler code is first grouped by event type, then a cascade of if statements selects it by option ID. While this clearly works, there are several issues with this approach:
- The handlers responsible for a single option are spread across the whole script. As the number of options grows, this becomes increasingly difficult to manage. For example, if you want to change an option, you'll have to find and modify code at many separate locations.
- You might also argue that as the number of option grows, it has to execute a lot of unnecessary checks, though performance is not the primary concern here.
- Changes are rarely limited to a single location in the script, which makes it easier to introduce bugs and harder to find them later.
With state options, we resolve these issues, because they allow to encapsulate the code responsible for an option in a single state.
Based on the earlier example, this is how the state option approach looks like:
event OnPageReset(string page)
AddToggleOptionST("OPTION_A", "A", true)
AddToggleOptionST("OPTION_B", "B", true)
...
AddToggleOptionST("OPTION_Z", "Z", true)
endEvent
state OPTION_A
event OnSelectST()
SetTextOptionValueST(true)
endEvent
event OnDefaultST()
SetTextOptionValueST(false)
endEvent
event OnHighlightST()
SetInfoText("Option A bla")
endEvent
endState
state OPTION_B
...
state OPTION_Z
event OnSelectST()
SetTextOptionValueST(true)
endEvent
event OnDefaultST()
SetTextOptionValueST(false)
endEvent
event OnHighlightST()
SetInfoText("Option Z bla")
endEvent
endState
Let's look at the most obvious changes:
- There's no more need for option IDs to be stored in variables. Instead, options are now uniquely named by the state, which contains their handlers.
- There are separate small handlers like
OnSelect
orOnDefault
for each option, instead of a single big one to handle all possibleOnSelect
events based on the passed option ID etc.
To understand how that fits in with the old API, let's summarize how options were managed previously:
- (1) They were added with the
Add*Option
functions inOnPageReset
. - (2) Option-specific events were handled in
event OnOption*(int option, ...)
. - (3)
Set*OptionValue(int option, ...)
andSetOptionFlags(int option, ...)
were used to change option data later.
These functions and events are now replaced by their state option equivalents (note the ST suffix):
- (1)
Add*OptionST(string stateName, ...)
replacesAdd*Option
. - (2) Multiple
OnSelectST
handlers in their respective states replaceOnOptionSelect
. The same happens for other option ID based events. - (3)
Set*OptionValueST
replacesSet*OptionValue(int option, ...)
,SetOptionFlagsST
replacesSetOptionFlags(int option, ...)
.