diff options
Diffstat (limited to 'Script.c')
| -rw-r--r-- | Script.c | 111 |
1 files changed, 76 insertions, 35 deletions
@@ -21,8 +21,6 @@ static const DT_Menu_Action_Normal = 0; static const DT_Menu_Action_Special2 = 1; static const DT_Menu_Action_Close = 2; -static const Menu_React_OverrideReaction = -1; -static const Menu_React_None = 0; static const Menu_React_Close = 1; static const Menu_React_Refresh = 2; static const Menu_React_KeepOpen = 3; @@ -30,6 +28,8 @@ static const Menu_React_Back = 4; static const Menu_React_SelectionOffset = 5; static const Menu_React_SelectionChange = 6; static const Menu_React_ShowSubMenu = 7; +static const Menu_React_OverrideReaction = -1; +static const Menu_React_None = nil; static const Menu_React_Max = Menu_React_ShowSubMenu; global func Menu_React_OffsetSelection(int offset) { return [Menu_React_SelectionOffset, offset]; } @@ -117,6 +117,7 @@ local columnCount; local columnEntries; local columnOffsets; local currentColumnSelections; +local shouldChangeColumn; local suspended; local closing; local refreshing; @@ -133,6 +134,7 @@ func Initialize() columnEntries = []; msgBoardEntry = []; vars = []; + currentColumn = 0; } func Destruction() @@ -147,7 +149,13 @@ func Create(map cSettings) multiColumnMode = false; columnCount = 0; - columnOffsets = []; + + var actualColumnCount = GetLength(currentColumnSelections); + columnOffsets = CreateArray(actualColumnCount); + for(var i = 0; i < actualColumnCount; ++i) + { + columnOffsets[i] = 0; + } if(settings.Vars) { @@ -188,8 +196,13 @@ func Create(map cSettings) for(var i = 0; i < GetLength(currentColumnSelections); ++i) { // TODO: cascade? then remove the columnSelection == -1 check; and check if shrinking menus still work correctly + if(!columnEntries[i]) + { + currentColumnSelections[i] = -1; + break; + } var columnSelection = currentColumnSelections[i]; - if((columnSelection == -1) || !columnEntries[i] || columnSelection >= GetLength(columnEntries[i])) + if((columnSelection == -1) || columnSelection >= GetLength(columnEntries[i])) { currentColumnSelections[i] = GetLength(columnEntries[i]) - 1; break; @@ -263,11 +276,15 @@ func SelectEntry(indexOrChain, int column) } else if(!indexOrChain || GetType(indexOrChain) == C4V_Int) { + column ??= 0; if(!(column >= 0 && column < GetLength(columnEntries) && GetType(columnEntries[column]) == C4V_Array)) { FatalError("Assertion failed: SelectEntry: column index out of range; assertion code: column >= 0 && column < GetLength(columnEntries) && GetType(columnEntries[column]) == C4V_Array"); } + indexOrChain ??= 0; var entryCount = GetLength(columnEntries[column]); if(indexOrChain < 0) indexOrChain = entryCount + indexOrChain; if(!(indexOrChain >= 0 && indexOrChain < entryCount)) { FatalError("Assertion failed: SelectEntry: selection index out of range; assertion code: indexOrChain >= 0 && indexOrChain < entryCount"); } + shouldChangeColumn = true; SelectMenuItem(EncodeSelection(indexOrChain, column), settings.Object); + shouldChangeColumn = false; } else { @@ -350,16 +367,16 @@ func FxMenuTimer(object target, int effectNumber, int effectTime) if(suspended) return; - if(msgBoardMode != 0 && !TestMessageBoard(GetOwner(settings.Object), true)) + if(msgBoardMode && !TestMessageBoard(GetOwner(settings.Object), true)) { var entry = columnEntries[msgBoardEntry[1]][msgBoardEntry[0]]; var args = entry.Args; - var reaction = CallCallbacks(args.Callbacks, Menu_CallbackType_InputAborted, [Menu_CallbackType_InputAborted, entry.Icon, settings.Object, entry.Args]); + var reaction = CallCallbacks(args?.Callbacks, Menu_CallbackType_InputAborted, [Menu_CallbackType_InputAborted, entry.Icon, settings.Object, entry.Args]); if(reaction != Menu_React_None) { React(reaction, msgBoardEntry); } - msgBoardMode = 0; + msgBoardMode = nil; } if(!GetMenu(settings.Object)) @@ -483,6 +500,7 @@ func HandleEntries(array factoryEntries, int& i, array& ret, map& retSettings, a for(var entry in factoryEntries) { + if(!(GetType(entry) == C4V_Map)) { FatalError(Format("Assertion failed: \"DT_Menu::HandleEntries: invalid entry. must be a map, got %v\"; assertion code: GetType(entry) == C4V_Map", entry)); } if(entry.Type == DT_Menu_Type_Entry) { if(multiColumnMode && isMainColumn) @@ -632,6 +650,7 @@ func AddEntries() { for(var j = 0; j < columnCount; ++j) { + columnOffsets[j] ??= 0; var rowIndex = i - columnOffsets[j]; var entries = columnEntries[j]; if(entries && rowIndex >= 0 && rowIndex < GetLength(entries)) @@ -723,7 +742,7 @@ func AddEntries() text = Format("%s {{MN7I:7}}", text); } - AddMenuItem(text, !noCommand && "MenuItemCommand", iconID, settings.Object, entry.Count, entryIndex, showDesc && entry.Description, entry.Extra, entry.XPar1, entry.XPar2); + AddMenuItem(text, !noCommand && "MenuItemCommand", iconID, settings.Object, entry.Count, entryIndex, showDesc && entry.Description || nil, entry.Extra, entry.XPar1, entry.XPar2); if(deleteIcon) { @@ -732,7 +751,7 @@ func AddEntries() } else { - AddMenuItem("", "DummyItemCommand", 0, settings.Object, 0, entryIndex, 0, C4MN_Add_ForceNoDesc); + AddMenuItem("", "DummyItemCommand", nil, settings.Object, nil, entryIndex, nil, C4MN_Add_ForceNoDesc); } ++entryIndex; } @@ -1001,30 +1020,40 @@ func OnMenuSelection(int selection, object menuObject) } // navigating between submenu columns; not in multiColumnMode - if(!multiColumnMode && (selection + columnOffsets[currentColumn] == oldColumnOldSelection + columnOffsets[oldColumn])) + if(!multiColumnMode) { - if(currentColumn == oldColumn + 1 && oldIsColumnSubMenu) + // navigated from one column to another without going over the left/right border + if(selection + columnOffsets[currentColumn] == oldColumnOldSelection + columnOffsets[oldColumn]) { - var targetSelection = columnEntries[currentColumn - 1][oldColumnOldSelection].SubMenuInitColumnData.Settings.Selection; - targetSelection = targetSelection && targetSelection[0]; - // column submenu was entered through pressing right; select the first entry - // but only if it's not there yet - if(selection != targetSelection) + if(currentColumn == oldColumn + 1 && oldIsColumnSubMenu) { - SelectEntry(targetSelection, currentColumn); - return; + var targetSelection = columnEntries[currentColumn - 1][oldColumnOldSelection].SubMenuInitColumnData.Settings.Selection; + targetSelection = targetSelection && targetSelection[0]; + // column submenu was entered through pressing right; select the first entry + // but only if it's not there yet + if(selection != targetSelection) + { + SelectEntry(targetSelection, currentColumn); + return; + } } - } - else if(currentColumn == oldColumn - 1) - { - // column submenu was left through pressing left; select the submenu entry - // but only if it's not there yet - if(selection != oldColumnSelection) + else if(currentColumn == oldColumn - 1) { - SelectEntry(oldColumnSelection, currentColumn); - return; + // column submenu was left through pressing left; select the submenu entry + // but only if it's not there yet + if(selection != oldColumnSelection) + { + SelectEntry(oldColumnSelection, currentColumn); + return; + } } } + else if(currentColumn != oldColumn && !shouldChangeColumn) // with going over the left/right border; we don’t want that + { + currentColumn = oldColumn; + SelectEntry(oldColumnOldSelection, oldColumn); + return; + } } if(skipHandling) @@ -1056,12 +1085,15 @@ func OnMenuSelection(int selection, object menuObject) else { var oldEntries = columnEntries[column + 1]; - SetLength(columnEntries, column + 1); - currentColumnSelections[column + 1] = -1; - if(oldEntries) + if (oldEntries != nil) { - Refresh([selection, column]); - return; + SetLength(columnEntries, column + 1); + currentColumnSelections[column + 1] = -1; + if(oldEntries) + { + Refresh([selection, column]); + return; + } } } } @@ -1139,11 +1171,12 @@ func HideInstantDescription() global func Menu_Callback(array callback, int types, array argBinding) { + types ??= Menu_CallbackType_Defaults; if(!(MN7I->CheckCallback(callback))) { FatalError("Assertion failed: Menu_Callback invalid callback used; assertion code: MN7I->CheckCallback(callback)"); } if(!((types & ~Menu_CallbackType_All) == 0)) { FatalError("Assertion failed: Menu_Callback: invalid callback type(s) used; assertion code: (types & ~Menu_CallbackType_All) == 0"); } argBinding = argBinding || [Menu_CallbackArg_Action, Menu_CallbackArg_Icon, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_NewSelection, Menu_CallbackArg_OldSelection, Menu_CallbackArg_NewValue, Menu_CallbackArg_OldValue, Menu_CallbackArg_FromSubMenu]; if(!(MN7I->ValidateMenuCallbackArgBinding(argBinding))) { FatalError("Assertion failed: Menu_Callback: invalid argBinding used; assertion code: MN7I->ValidateMenuCallbackArgBinding(argBinding)"); } - return [callback, types || Menu_CallbackType_Defaults, argBinding]; + return [callback, types, argBinding]; } global func Menu_Entry_VariableCondition(array scopedVar, compare, int disableMode, bool invert, int allowDisabledSelection) @@ -1203,7 +1236,8 @@ global func Menu_Entry(map entry) { entry = Extend({ Text = "", - Placeholder = -1 + Placeholder = -1, + Extra = 0, }, entry, true); } @@ -1614,6 +1648,7 @@ func AdaptorFactory(args, int entryIndex, int entryColumn) else if(args.Type == Menu_AdaptorType_Integer) { if(!(GetType(val) == C4V_Any || GetType(val) == C4V_Int)) { FatalError("Assertion failed: AdaptorFactory: Value of Menu_Adaptor_Variable has wrong type; assertion code: GetType(val) == C4V_Any || GetType(val) == C4V_Int"); } + val ??= 0; var limits = AdaptorGetLimits(args.Limits), max, min; var wrapAround = args.WrapAround; if(limits && !wrapAround) @@ -1684,7 +1719,7 @@ func AdaptorFactory(args, int entryIndex, int entryColumn) } else { - return [Menu_SubMenu({ Entry = Extend(entrySettings, { Text = text, Callbacks = [Menu_Callback(MenuObjectCallback("AdaptorCommand"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])], Icon = icon, Description = description, Args = args }, true), Entries = retSubMenu }, GetType(args.Enum.SubMenu.On) == C4V_Bool) && args.Enum.SubMenu.On]; + return [Menu_SubMenu({ Entry = Extend(entrySettings, { Text = text, Callbacks = [Menu_Callback(MenuObjectCallback("AdaptorCommand"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])], Icon = icon, Description = description, Args = args }, true), Entries = retSubMenu }, GetType(args.Enum.SubMenu.On) == C4V_Bool && args.Enum.SubMenu.On)]; } } @@ -1754,6 +1789,10 @@ func AdaptorEnumSubMenuFactory(map args) { BooleanToggleText(i == index, text, icon); } + else if(i == index) + { + ExtraIcon(text, icon, [MN7I, 1]); + } ret.Entries[] = Menu_Entry({ Text = text, Icon = icon, @@ -2193,7 +2232,8 @@ global func CreateNewMenu(map settings, map inheritSettings, object parentMenu) Decoration = DT_Menu_DefaultInstantDescriptionDecoration, Flags = MSG_Left | MSG_Bottom, Position = [40, -60] - } + }, + KeepOpen = Menu_KeepOpen_Not, } }, { Settings = inheritSettings }, true), { Settings = { @@ -2300,6 +2340,7 @@ func Update() func GetSelection(int mode) { + mode ??= Menu_Selection_Simple; if(mode == Menu_Selection_Simple) { return currentColumnSelections[currentColumn]; |
