diff options
| -rw-r--r-- | Script.c | 1138 |
1 files changed, 547 insertions, 591 deletions
@@ -1,47 +1,21 @@ #strict 2 static const DT_Menu = MN7I; -static const DT_Menu_Combined = -1; static const DT_Menu_MenuVar = -1; // Enums and bitfields -static const DT_Menu_Settings_Icon = 0; -static const DT_Menu_Settings_Object = 1; -static const DT_Menu_Settings_Extra = 2; -static const DT_Menu_Settings_Title = 3; -static const DT_Menu_Settings_ExtraData = 4; -static const DT_Menu_Settings_Style = 5; -static const DT_Menu_Settings_KeepOpen = 6; -static const DT_Menu_Settings_Parent = 7; -static const DT_Menu_Settings_Size = 8; -static const DT_Menu_Settings_RefreshInterval = 9; -static const DT_Menu_Settings_Selection = 10; -static const DT_Menu_Settings_ConditionDisableMode = 11; -static const DT_Menu_Settings_ConditionAllowSelection = 12; -static const DT_Menu_Settings_Callbacks = 13; -static const DT_Menu_Settings_Decoration = 14; -static const DT_Menu_Settings_RequireAction = 15; -static const DT_Menu_Settings_KeepParentOnClose = 16; -static const DT_Menu_Settings_Vars = 17; -static const DT_Menu_Settings_Closable = 18; -static const DT_Menu_Settings_InstantDescription = 19; -static const DT_Menu_Settings_InstantDescriptionFlags = 20; -static const DT_Menu_Settings_InstantDescriptionPosition = 21; -static const DT_Menu_Settings_InstantDescriptionDecoration = 22; - -static const DT_Menu_KeepOpen_Not = 0x0; -static const DT_Menu_KeepOpen_Keep = 0x1; -static const DT_Menu_KeepOpen_Force = 0x2; -static const DT_Menu_KeepOpen_Permanent = 0x4; -static const DT_Menu_KeepOpen_Refresh = 0x8; -static const DT_Menu_KeepOpen_RefreshContinuously = 0x10; -static const DT_Menu_KeepOpen_Refresh_Mask = 0x18; // DT_Menu_KeepOpen_Refresh | DT_Menu_KeepOpen_RefreshContinuously - -static const DT_Menu_Type_Setting = 0; -static const DT_Menu_Type_Entry = 1; -static const DT_Menu_Type_Factory = 2; -static const DT_Menu_Type_Columns = 3; +static const Menu_KeepOpen_Not = 0x0; +static const Menu_KeepOpen_Keep = 0x1; +static const Menu_KeepOpen_Force = 0x2; +static const Menu_KeepOpen_Permanent = 0x4; +static const Menu_KeepOpen_Refresh = 0x8; +static const Menu_KeepOpen_RefreshContinuously = 0x10; +static const Menu_KeepOpen_Refresh_Mask = 0x18; // Menu_KeepOpen_Refresh | Menu_KeepOpen_RefreshContinuously + +static const DT_Menu_Type_Entry = 0; +static const DT_Menu_Type_Factory = 1; +static const DT_Menu_Type_Columns = 2; static const DT_Menu_Action_Normal = 0; static const DT_Menu_Action_Special2 = 1; @@ -55,7 +29,7 @@ static const Menu_React_KeepOpen = 3; 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_ShowSubMenu = 7; global func Menu_React_OffsetSelection(int offset) { return [Menu_React_SelectionOffset, offset]; } global func Menu_React_OverrideSelection(int override) { return [Menu_React_SelectionChange, override]; } @@ -74,20 +48,6 @@ static const Menu_Condition_Default = 0; static const Menu_Condition_AllowSelection = 1; static const Menu_Condition_DenySelection = 2; -static const DT_Menu_Entry_Text = 0; -static const DT_Menu_Entry_Callbacks = 1; -static const DT_Menu_Entry_Icon = 2; -static const DT_Menu_Entry_Count = 3; -static const DT_Menu_Entry_Description = 4; -static const DT_Menu_Entry_Extra = 5; -static const DT_Menu_Entry_XPar1 = 6; -static const DT_Menu_Entry_XPar2 = 7; -static const DT_Menu_Entry_Args = 8; -static const DT_Menu_Entry_Condition = 9; -static const DT_Menu_Entry_Placeholder = 10; -static const DT_Menu_Entry_InstantDescriptionIcon = 11; -static const DT_Menu_Entry_SubMenuColumnData = 12; - static const Menu_CallbackType_None = 0x0; static const Menu_CallbackType_Special2 = 0x1; static const Menu_CallbackType_Normal = 0x2; @@ -99,12 +59,12 @@ static const Menu_CallbackType_InputAborted = 0x40; static const Menu_CallbackType_Defaults = 0x3; // Menu_CallbackType_Normal | Menu_CallbackType_Special2 static const Menu_CallbackType_All = 0x7f; // Menu_CallbackType_Normal | Menu_CallbackType_Special2 | Menu_CallbackType_Close | Menu_CallbackType_Selection | Menu_CallbackType_Deselection | Menu_CallbackType_ValueChanged | Menu_CallbackType_InputAborted -static const Menu_AdaptorType_Boolean = 0; -static const Menu_AdaptorType_Integer = 1; -static const Menu_AdaptorType_String = 2; -static const Menu_AdaptorType_ID = 3; -static const Menu_AdaptorType_Enum = 4; -static const Menu_AdaptorType_BitField = 5; +static const Menu_AdaptorType_Boolean = 1; +static const Menu_AdaptorType_Integer = 2; +static const Menu_AdaptorType_String = 3; +static const Menu_AdaptorType_ID = 4; +static const Menu_AdaptorType_Enum = 5; +static const Menu_AdaptorType_BitField = 6; static const Menu_Adaptor_Limits_Max = 0x7fffffff; static const Menu_Adaptor_Limits_Min = 0x80000000; @@ -118,7 +78,7 @@ static const Menu_CallbackArg_NewSelection = 4; static const Menu_CallbackArg_OldSelection = 5; static const Menu_CallbackArg_NewValue = 6; static const Menu_CallbackArg_OldValue = 7; -static const Menu_CallbackArg_FromSubmenu = 8; +static const Menu_CallbackArg_FromSubMenu = 8; static const Menu_CallbackArg_Menu = 9; static const Menu_CallbackArg_Returned = 10; static const Menu_CallbackArg_Menu = 11; @@ -127,24 +87,6 @@ static const Menu_CallbackArg_EntryColumn = 13; static const Menu_CallbackArg_NewSelectionColumn = 14; static const Menu_CallbackArg_OldSelectionColumn = 15; -static const DT_Menu_Adaptor_Type = 0; -static const DT_Menu_Adaptor_Variable = 1; -static const DT_Menu_Adaptor_Callbacks = 2; -static const DT_Menu_Adaptor_MessageBoardText = 3; -static const DT_Menu_Adaptor_Limits = 4; -static const DT_Menu_Adaptor_StepSize = 5; -static const DT_Menu_Adaptor_LayoutVals = 6; -static const DT_Menu_Adaptor_NoEmptyString = 7; -static const DT_Menu_Adaptor_EntryIndex = 8; -static const DT_Menu_Adaptor_Mask = 9; -static const DT_Menu_Adaptor_WrapAround = 10; -static const DT_Menu_Adaptor_Args = 11; -static const DT_Menu_Adaptor_EnumSubmenu = 12; -static const DT_Menu_Adaptor_EnumSubmenuTitleAndText = 13; -static const DT_Menu_Adaptor_EnumSubmenuIcon = 14; -static const DT_Menu_Adaptor_EnumAllowUnknown = 15; -static const DT_Menu_Adaptor_EnumInline = 16; - static const Menu_Selection_Simple = 0; static const Menu_Selection_WithColumn = 1; static const Menu_Selection_SubMenuColumnChain = 2; @@ -193,25 +135,18 @@ func Destruction() Close(); } -func Create(array cSettings, array cEntries) +func Create(map cSettings) { - settings = cSettings; - createEntries = cEntries; - settings[DT_Menu_Settings_ConditionDisableMode] = settings[DT_Menu_Settings_ConditionDisableMode] || Menu_ConditionReact_Hide; - settings[DT_Menu_Settings_InstantDescriptionDecoration] = settings[DT_Menu_Settings_InstantDescriptionDecoration] || DT_Menu_DefaultInstantDescriptionDecoration; - if(!settings[DT_Menu_Settings_InstantDescriptionPosition]) - { - settings[DT_Menu_Settings_InstantDescriptionFlags] = settings[DT_Menu_Settings_InstantDescriptionFlags] || MSG_Left | MSG_Bottom; - settings[DT_Menu_Settings_InstantDescriptionPosition] = [40, -60]; - } + settings = cSettings.Settings; + createEntries = cSettings.Entries; multiColumnMode = false; columnCount = 0; columnOffsets = []; - if(settings[DT_Menu_Settings_Vars]) + if(settings.Vars) { - var settingVars = settings[DT_Menu_Settings_Vars]; + var settingVars = settings.Vars; for(var i = 0; i < GetLength(settingVars); ++i) { @@ -220,21 +155,21 @@ func Create(array cSettings, array cEntries) vars[i] = settingVars[i]; } } - settings[DT_Menu_Settings_Vars] = 0; + settings.Vars = 0; } var factoryArgs = []; factoryArgs[Menu_CallbackArg_Menu] = this; - factoryArgs[Menu_CallbackArg_MenuObject] = settings[DT_Menu_Settings_Object]; + factoryArgs[Menu_CallbackArg_MenuObject] = settings.Object; var index = 0; columnEntries[0] = []; HandleEntries(createEntries, index, columnEntries[0], settings, factoryArgs, 0, true); - if(settings[DT_Menu_Settings_Parent]) settings[DT_Menu_Settings_Parent]->Suspend(); + if(settings.Parent) settings.Parent->Suspend(); - var title = settings[DT_Menu_Settings_Title]; + var title = settings.Title; if(!multiColumnMode) { @@ -250,19 +185,19 @@ func Create(array cSettings, array cEntries) break; } - var submenuData = columnEntries[i][columnSelection][DT_Menu_Entry_SubMenuColumnData]; - if(submenuData) + var submenuEntries = columnEntries[i][columnSelection].SubMenuColumnEntries; + if(submenuEntries) { - columnEntries[i + 1] = submenuData[2]; + columnEntries[i + 1] = submenuEntries; - var submenuSettings = submenuData[0]; - /*var */submenuTitle = submenuSettings[DT_Menu_Settings_Title] || ""; - if(submenuSettings[DT_Menu_Settings_Icon]) + var submenuSettings = columnEntries[i][columnSelection].SubMenuInitColumnData.Settings; + /*var */submenuTitle = submenuSettings.Title || ""; + if(submenuSettings.Icon) { - submenuTitle = Format("{{%i}} %s", submenuSettings[DT_Menu_Settings_Icon], submenuTitle); + submenuTitle = Format("{{%i}} %s", submenuSettings.Icon, submenuTitle); } - // because of the engine such long titles are not nice; maybe do "... > last Submenu Title" + // because of the engine such long titles are not nice; maybe do "... > last SubMenu Title" // the engine makes entry columns at least as long as the title is... // title = Format("%s {{MN7I:7}} %s", title, submenuTitle); } @@ -274,8 +209,8 @@ func Create(array cSettings, array cEntries) } } - CreateMenu(settings[DT_Menu_Settings_Icon], settings[DT_Menu_Settings_Object], this, settings[DT_Menu_Settings_Extra], title, settings[DT_Menu_Settings_ExtraData], settings[DT_Menu_Settings_Style], true, MN7I); - if(GetType(settings[DT_Menu_Settings_Size]) == C4V_Array) SetMenuSize(settings[DT_Menu_Settings_Size][0], settings[DT_Menu_Settings_Size][1], settings[DT_Menu_Settings_Object]); + CreateMenu(settings.Icon, settings.Object, this, settings.Extra, title, settings.ExtraData, settings.Style, true, MN7I); + if(settings.Size) SetMenuSize(settings.Size[0], settings.Size[1], settings.Object); AddEntries(); @@ -283,13 +218,13 @@ func Create(array cSettings, array cEntries) { if(!refreshing) { - SelectEntry(settings[DT_Menu_Settings_Selection][0], settings[DT_Menu_Settings_Selection][1]); + SelectEntry(settings.Selection[0], settings.Selection[1]); } } - if(settings[DT_Menu_Settings_Decoration]) + if(settings.Decoration) { - SetMenuDecoration(settings[DT_Menu_Settings_Decoration], settings[DT_Menu_Settings_Object]); + SetMenuDecoration(settings.Decoration, settings.Object); } if(!GetEffect("Menu", this)) AddEffect("Menu", this, 1, 1, this, 0); @@ -314,7 +249,7 @@ func SelectEntry(indexOrChain, int column) { var entryCount = GetLength(columnEntries[column]); if(indexOrChain < 0) indexOrChain = entryCount + indexOrChain; - SelectMenuItem(EncodeSelection(indexOrChain, column), settings[DT_Menu_Settings_Object]); + SelectMenuItem(EncodeSelection(indexOrChain, column), settings.Object); } else { @@ -326,7 +261,7 @@ func SelectTopEntry(int column) { for(var i = 0; i < GetLength(columnEntries[column]); ++i) { - if(columnEntries[column][i][DT_Menu_Entry_Placeholder]) + if(columnEntries[column][i].Placeholder) { return SelectEntry(i, column); } @@ -337,7 +272,7 @@ func SelectBottomEntry(int column) { for(var i = GetLength(columnEntries[column]) - 1; i >= 0; --i) { - if(columnEntries[column][i][DT_Menu_Entry_Placeholder]) + if(columnEntries[column][i].Placeholder) { return SelectEntry(i, column); } @@ -356,7 +291,7 @@ func ActivateEntry(int action, indexOrChain, int column) } var entry = columnEntries[column][index]; - MenuItemCommand(entry[DT_Menu_Entry_Icon], EncodeSelection(index, column), action); + MenuItemCommand(entry.Icon, EncodeSelection(index, column), action); } func SubMenu() @@ -381,14 +316,14 @@ global func MenuVar(int index) func FxMenuTimer(object target, int effectNumber, int effectTime) { - if(!settings[DT_Menu_Settings_Object]) + if(!settings.Object) { return Close(); } - else if(settings[DT_Menu_Settings_RequireAction]) + else if(settings.RequireAction) { - var obj = settings[DT_Menu_Settings_Object]; - var requirement = settings[DT_Menu_Settings_RequireAction]; + var obj = settings.Object; + var requirement = settings.RequireAction; if(GetAction(obj) != requirement[0] || (requirement[1] && GetActionTarget(0, obj) != requirement[1])) { return Close(); @@ -397,11 +332,11 @@ func FxMenuTimer(object target, int effectNumber, int effectTime) if(suspended) return; - if(msgBoardMode != 0 && !TestMessageBoard(GetOwner(settings[DT_Menu_Settings_Object]), true)) + if(msgBoardMode != 0 && !TestMessageBoard(GetOwner(settings.Object), true)) { var entry = columnEntries[msgBoardEntry[1]][msgBoardEntry[0]]; - var args = entry[DT_Menu_Entry_Args]; - var reaction = CallCallbacks(args[DT_Menu_Adaptor_Callbacks], Menu_CallbackType_InputAborted, [Menu_CallbackType_InputAborted, entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args]]); + var args = 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); @@ -409,9 +344,9 @@ func FxMenuTimer(object target, int effectNumber, int effectTime) msgBoardMode = 0; } - if(!GetMenu(settings[DT_Menu_Settings_Object])) + if(!GetMenu(settings.Object)) { - if(settings[DT_Menu_Settings_KeepOpen] & (DT_Menu_KeepOpen_Refresh_Mask | DT_Menu_KeepOpen_Force) && !settings[DT_Menu_Settings_Closable]) + if(settings.KeepOpen & (Menu_KeepOpen_Refresh_Mask | Menu_KeepOpen_Force) && !settings.Closable) { Refresh(GetSelection(Menu_Selection_WithColumn)); } @@ -421,7 +356,7 @@ func FxMenuTimer(object target, int effectNumber, int effectTime) } } - if(settings[DT_Menu_Settings_KeepOpen] & DT_Menu_KeepOpen_RefreshContinuously && !(effectTime % settings[DT_Menu_Settings_RefreshInterval])) + if(settings.KeepOpen & Menu_KeepOpen_RefreshContinuously && !(effectTime % settings.RefreshInterval)) { Refresh(GetSelection(Menu_Selection_WithColumn)); } @@ -433,9 +368,9 @@ func FxMenuStop(object target, int effectNumber, int reason, bool temp) { return; } - CloseMenu(settings[DT_Menu_Settings_Object]); - if(settings[DT_Menu_Settings_InstantDescription]) HideInstantDescription(); - if(settings[DT_Menu_Settings_Parent]) settings[DT_Menu_Settings_Parent]->Suspend(true); + CloseMenu(settings.Object); + if(settings.InstantDescription.Enable) HideInstantDescription(); + if(settings.Parent) settings.Parent->Suspend(true); RemoveObject(this); } @@ -481,7 +416,7 @@ func CallCallbacks(array callbacks, int type, array args, defaultRet, bool noGlo if(!noGlobalCallbacks) { args[Menu_CallbackArg_Returned] = ret; - var globalRet = CallCallbacks(settings[DT_Menu_Settings_Callbacks], type, args, defaultRet, true); + var globalRet = CallCallbacks(settings.Callbacks, type, args, defaultRet, true); if(GetType(globalRet) == C4V_Array && globalRet[0] == Menu_React_OverrideReaction) { ret = globalRet[1]; @@ -498,7 +433,7 @@ func Close(bool closeParents) { subMenu->Close(); } - if(closeParents && settings[DT_Menu_Settings_Parent]) settings[DT_Menu_Settings_Parent]->Close(true); + if(closeParents && settings.Parent) settings.Parent->Close(true); RemoveEffect("Menu", this); } @@ -507,7 +442,7 @@ func Suspend(bool cont) if(suspended == !cont) return; if(suspended = !cont) { - CloseMenu(settings[DT_Menu_Settings_Object]); + CloseMenu(settings.Object); } else if(!closing) { @@ -515,7 +450,7 @@ func Suspend(bool cont) } } -func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, array& factoryArgs, int column, bool isMainColumn) +func HandleEntries(array factoryEntries, int& i, array& ret, map& retSettings, array& factoryArgs, int column, bool isMainColumn) { if(column >= columnCount) { @@ -524,48 +459,70 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, for(var entry in factoryEntries) { - if(entry[0] == DT_Menu_Type_Entry) + if(entry.Type == DT_Menu_Type_Entry) { if(multiColumnMode && isMainColumn) { FatalError("DT_Menu::HandleEntries: if Menu_Columns() is used, all entries must occur inside it"); } // is it an extra column submenu? - if(entry[2]) + if(entry.SubMenuInitColumnData) { if(multiColumnMode) { - FatalError("DT_Menu::HandleEntries: Menu_Columns() and Submenu columns can not be used together"); + FatalError("DT_Menu::HandleEntries: Menu_Columns() and SubMenu columns can not be used together"); + } + + if(!entry.SubMenuInitColumnData.Settings) + { + entry.SubMenuInitColumnData.Settings = {}; } var index = 0; - HandleEntries(entry[2][1], index, entry[2][2], entry[2][0], factoryArgs, column + 1, false); - entry[1][DT_Menu_Entry_SubMenuColumnData] = entry[2]; + HandleEntries(entry.SubMenuInitColumnData.Entries, index, entry.SubMenuColumnEntries = [], entry.SubMenuInitColumnData.Settings, factoryArgs, column + 1, false); } - ret[i++] = entry[1]; + ret[i++] = entry; } - else if(entry[0] == DT_Menu_Type_Factory) + else if(entry.Type == DT_Menu_Type_Factory) { - for(var callback in entry[1][0]) + for(var callback in entry.Callbacks) { - factoryArgs[Menu_CallbackArg_Args] = entry[1][1]; + factoryArgs[Menu_CallbackArg_Args] = entry.Args; factoryArgs[Menu_CallbackArg_EntryNumber] = i; factoryArgs[Menu_CallbackArg_EntryColumn] = column; - var factoryResult = CallA(callback, BindCallbackArgs(factoryArgs, entry[1][2])); - if(GetType(factoryResult) == C4V_Array) + var factoryResult = CallA(callback, BindCallbackArgs(factoryArgs, entry.Binding)); + + if(factoryResult == Menu_React_Close) { - var newEntries = []; - UncombineAndDistinguish(factoryResult, retSettings, newEntries); - HandleEntries(newEntries, i, ret, retSettings, factoryArgs, column, isMainColumn); + return Close(); } - else if(factoryResult == Menu_React_Close) + else { - return Close(); + var newSettings; + var newEntries; + if(GetType(factoryResult) == C4V_Map) + { + newSettings = factoryResult.Settings; + newEntries = factoryResult.Entries; + } + else if(GetType(factoryResult) == C4V_Array) + { + newEntries = factoryResult; + } + + if(newSettings) + { + retSettings = Extend(retSettings, newSettings, true); + } + if(newEntries) + { + HandleEntries(newEntries, i, ret, retSettings, factoryArgs, column, isMainColumn); + } } - } + } } - else if(entry[0] == DT_Menu_Type_Columns) + else if(entry.Type == DT_Menu_Type_Columns) { if(multiColumnMode) { @@ -574,7 +531,7 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, if(columnCount > 1) { - FatalError("DT_Menu::HandleEntries: Menu_Columns() and Submenu columns can not be used together"); + FatalError("DT_Menu::HandleEntries: Menu_Columns() and SubMenu columns can not be used together"); } if(GetLength(columnEntries[0]) > 0) @@ -585,13 +542,14 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, multiColumnMode = true; var j = 0; - for(var columnData in entry[1]) + for(var columnData in entry.Columns) { columnEntries[j] = []; var index = 0; - var tempSettings = []; - HandleEntries(columnData, index, columnEntries[j], settings, factoryArgs, j, false); + var tempSettings = {}; + // NOTE: First instead of tempSettings, settings was used. Seems wrong. + HandleEntries(columnData, index, columnEntries[j], tempSettings, factoryArgs, j, false); ++j; if(GetLength(tempSettings) > 0) @@ -617,7 +575,7 @@ func AddEntries() if(columnCount > 1) { - SetMenuSize(columnCount, entriesCount, settings[DT_Menu_Settings_Object]); + SetMenuSize(columnCount, entriesCount, settings.Object); } if(!multiColumnMode) @@ -647,17 +605,17 @@ func AddEntries() if(entries && rowIndex >= 0 && rowIndex < GetLength(entries)) { var entry = entries[rowIndex]; - var condition = entry[DT_Menu_Entry_Condition], conditionRet; - var text = entry[DT_Menu_Entry_Text], noCommand = !entry[DT_Menu_Entry_Placeholder] || (entry[DT_Menu_Entry_Placeholder] != true && !entry[DT_Menu_Entry_Callbacks]); + var condition = entry.Condition, conditionRet; + var text = entry.Text, noCommand = !entry.Placeholder || (entry.Placeholder != true && !entry.Callbacks); if(condition) { - if(noCommand || condition[1] == Menu_Condition_DenySelection || (condition[1] == Menu_Condition_Default && !settings[DT_Menu_Settings_ConditionAllowSelection])) + if(noCommand || condition.AllowDisabledSelection == Menu_Condition_DenySelection || (condition.AllowDisabledSelection == Menu_Condition_Default && !settings.Condition.AllowSelection)) { noCommand = true; } - conditionRet = CallA(condition[0], [entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args]]) || settings[DT_Menu_Settings_ConditionDisableMode]; - if(conditionRet == Menu_ConditionReact_Hide) + conditionRet = CallA(condition.Callback, [entry.Icon, settings.Object, entry.Args]) || settings.Condition.DisableMode; + if(conditionRet == Menu_ConditionReact_Hide) { continue; } @@ -675,7 +633,7 @@ func AddEntries() } } - var icon = entry[DT_Menu_Entry_Icon], iconIndex = 0, iconID = 0, deleteIcon = 0; + var icon = entry.Icon, iconIndex = 0, iconID = 0, deleteIcon = 0; if(GetType(icon) == C4V_Array) { if(GetType(icon[0]) == C4V_C4ID) @@ -687,16 +645,16 @@ func AddEntries() } else if(icon[1]) { - entry[DT_Menu_Entry_Extra] |= C4MN_Add_ImgIndexed; + entry.Extra |= C4MN_Add_ImgIndexed; iconIndex = icon[1]; - entry[DT_Menu_Entry_XPar1] = icon[1]; + entry.XPar1 = icon[1]; } } if(GetType(icon[0]) == C4V_C4Object) { - entry[DT_Menu_Entry_Extra] |= C4MN_Add_ImgObject; - entry[DT_Menu_Entry_XPar1] = icon[0]; + entry.Extra |= C4MN_Add_ImgObject; + entry.XPar1 = icon[0]; if(icon[1]) { deleteIcon = icon[0]; @@ -711,29 +669,29 @@ func AddEntries() { iconID = icon; } - entry[DT_Menu_Entry_Icon] = iconID; + entry.Icon = iconID; - if(!entry[DT_Menu_Entry_InstantDescriptionIcon]) + if(!entry.InstantDescriptionIcon) { - entry[DT_Menu_Entry_InstantDescriptionIcon] = [iconID, iconIndex]; + entry.InstantDescriptionIcon = [iconID, iconIndex]; } - if(settings[DT_Menu_Settings_InstantDescription]) + if(settings.InstantDescription.Enable) { - entry[DT_Menu_Entry_Extra] |= C4MN_Add_ForceNoDesc; + entry.Extra |= C4MN_Add_ForceNoDesc; } - entry[DT_Menu_Entry_Placeholder] = !noCommand; + entry.Placeholder = !noCommand; columnEntries[j][rowIndex] = entry; - var showDesc = !(entry[DT_Menu_Entry_Extra] & C4MN_Add_ForceNoDesc); + var showDesc = !(entry.Extra & C4MN_Add_ForceNoDesc); - if(entry[DT_Menu_Entry_SubMenuColumnData] && currentColumnSelections[j] == rowIndex) + if(entry.SubMenuInitColumnData && currentColumnSelections[j] == rowIndex) { text = Format("%s {{MN7I:7}}", text); } - AddMenuItem(text, !noCommand && "MenuItemCommand", iconID, settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Count], entryIndex, showDesc && entry[DT_Menu_Entry_Description], entry[DT_Menu_Entry_Extra], entry[DT_Menu_Entry_XPar1], entry[DT_Menu_Entry_XPar2]); + AddMenuItem(text, !noCommand && "MenuItemCommand", iconID, settings.Object, entry.Count, entryIndex, showDesc && entry.Description, entry.Extra, entry.XPar1, entry.XPar2); if(deleteIcon) { @@ -742,7 +700,7 @@ func AddEntries() } else { - AddMenuItem("", "DummyItemCommand", 0, settings[DT_Menu_Settings_Object], 0, entryIndex, 0, C4MN_Add_ForceNoDesc); + AddMenuItem("", "DummyItemCommand", 0, settings.Object, 0, entryIndex, 0, C4MN_Add_ForceNoDesc); } ++entryIndex; } @@ -753,7 +711,7 @@ func React(reaction, array entryIndex, int refreshDelayed) { if(reaction == Menu_React_Close) { - Close(!settings[DT_Menu_Settings_KeepParentOnClose]); + Close(!settings.KeepParentOnClose); } else if(reaction == Menu_React_Back) { @@ -766,7 +724,7 @@ func React(reaction, array entryIndex, int refreshDelayed) Close(); } } - else if(reaction == Menu_React_Refresh || (settings[DT_Menu_Settings_KeepOpen] & DT_Menu_KeepOpen_Refresh)) + else if(reaction == Menu_React_Refresh || (settings.KeepOpen & Menu_KeepOpen_Refresh)) { Refresh(entryIndex, refreshDelayed); } @@ -791,26 +749,26 @@ func React(reaction, array entryIndex, int refreshDelayed) } } -func CheckCondition(array entry) +func CheckCondition(map entry) { - var condition = entry[DT_Menu_Entry_Condition]; - return !condition || (CallA(condition[0], [entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args]]) || settings[DT_Menu_Settings_ConditionDisableMode]) == Menu_ConditionReact_Show; + var condition = entry.Condition; + return !condition || (CallA(condition.Callback, [entry.Icon, settings.Object, entry.Args]) || settings.Condition.DisableMode) == Menu_ConditionReact_Show; } func MenuItemCommand(id ID, int itemNumber, int action) { var column = DecodeSelection(itemNumber); var entry = columnEntries[column][itemNumber]; - var condition = entry[DT_Menu_Entry_Condition]; + var condition = entry.Condition; action = action || Menu_CallbackType_Normal; var reaction; if(CheckCondition(entry)) { - reaction = CallCallbacks(entry[DT_Menu_Entry_Callbacks], action, [action, ID, settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args]]); + reaction = CallCallbacks(entry.Callbacks, action, [action, ID, settings.Object, entry.Args]); } else { - if(condition[1] == Menu_Condition_AllowSelection) + if(condition.AllowDisabledSelection == Menu_Condition_AllowSelection) { reaction = Menu_React_KeepOpen; } @@ -830,16 +788,16 @@ func DummyItemCommand(id ID, int itemNumber, int action) React(Menu_React_KeepOpen, [itemNumber, column]); } -func SubmenuItemCallback(int action, object menuObject, args, array allArgs) +func SubMenuItemCallback(int action, object menuObject, args, array allArgs) { allArgs[Menu_CallbackArg_Args] = args[1]; var reaction = CallCallbacks(args[0], action, allArgs, Menu_React_None); - if(((action & Menu_CallbackType_Defaults) && reaction == Menu_React_None) || reaction == Menu_React_ShowSubmenu) + if(((action & Menu_CallbackType_Defaults) && reaction == Menu_React_None) || reaction == Menu_React_ShowSubMenu) { if(args[3]) { - var targetSelection = columnEntries[currentColumn][currentColumnSelections[currentColumn]][DT_Menu_Entry_SubMenuColumnData][0][DT_Menu_Settings_Selection]; + var targetSelection = columnEntries[currentColumn][currentColumnSelections[currentColumn]].SubMenuInitColumnData.Settings.Selection; SelectEntry(targetSelection && targetSelection[0], currentColumn + 1); } else @@ -876,13 +834,13 @@ func MenuQueryCancel(int selection, object menuObject) var entry = columnEntries[column][selection]; if(CheckCondition(entry)) { - reaction = CallCallbacks(entry[DT_Menu_Entry_Callbacks], Menu_CallbackType_Close, [Menu_CallbackType_Close, entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args]]); + reaction = CallCallbacks(entry.Callbacks, Menu_CallbackType_Close, [Menu_CallbackType_Close, entry.Icon, settings.Object, entry.Args]); } React(reaction, [selection, column], true); } - if((settings[DT_Menu_Settings_KeepOpen] != DT_Menu_KeepOpen_Not && settings[DT_Menu_Settings_KeepOpen] != DT_Menu_KeepOpen_Permanent && !settings[DT_Menu_Settings_Closable]) || (reaction == Menu_React_KeepOpen)) + if((settings.KeepOpen != Menu_KeepOpen_Not && settings.KeepOpen != Menu_KeepOpen_Permanent && !settings.Closable) || (reaction == Menu_React_KeepOpen)) { return true; } @@ -896,6 +854,7 @@ func OnMenuSelection(int selection, object menuObject) // selections can be out of range if dummy entries get selected // let's emulate some engine behavior then + // TODO: Fix stack overflow when the target selection can't be selected (Placeholder) if(!columnEntries[column]) { // navigate downwards when pressing right at the right border (thus selecting a dummy) @@ -977,23 +936,23 @@ func OnMenuSelection(int selection, object menuObject) var selectReaction = Menu_React_None; if(!noSelectionCallbacks && CheckCondition(entry) && oldColumnSelection != -1) { - var args = [Menu_CallbackType_Deselection, entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args], selection, oldColumnSelection]; + var args = [Menu_CallbackType_Deselection, entry.Icon, settings.Object, entry.Args, selection, oldColumnSelection]; args[Menu_CallbackArg_NewSelectionColumn] = currentColumn; args[Menu_CallbackArg_OldSelectionColumn] = oldColumn; - deselectReaction = CallCallbacks(entry[DT_Menu_Entry_Callbacks], Menu_CallbackType_Deselection, args); + deselectReaction = CallCallbacks(entry.Callbacks, Menu_CallbackType_Deselection, args); } - var oldIsColumnSubmenu = !!entry[DT_Menu_Entry_SubMenuColumnData]; + var oldIsColumnSubMenu = !!entry.SubMenuInitColumnData; currentColumnSelections[column] = selection; entry = columnEntries[column][selection]; if(!noSelectionCallbacks && CheckCondition(entry)) { - var args = [Menu_CallbackType_Selection, entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], entry[DT_Menu_Entry_Args], selection, oldColumnSelection]; + var args = [Menu_CallbackType_Selection, entry.Icon, settings.Object, entry.Args, selection, oldColumnSelection]; args[Menu_CallbackArg_NewSelectionColumn] = currentColumn; args[Menu_CallbackArg_OldSelectionColumn] = oldColumn; - selectReaction = CallCallbacks(entry[DT_Menu_Entry_Callbacks], Menu_CallbackType_Selection, args); + selectReaction = CallCallbacks(entry.Callbacks, Menu_CallbackType_Selection, args); } if(deselectReaction != Menu_React_None) @@ -1012,9 +971,9 @@ func OnMenuSelection(int selection, object menuObject) // navigating between submenu columns; not in multiColumnMode if(!multiColumnMode && (selection + columnOffsets[currentColumn] == oldColumnOldSelection + columnOffsets[oldColumn])) { - if(currentColumn == oldColumn + 1 && oldIsColumnSubmenu) + if(currentColumn == oldColumn + 1 && oldIsColumnSubMenu) { - var targetSelection = columnEntries[currentColumn - 1][oldColumnOldSelection][DT_Menu_Entry_SubMenuColumnData][0][DT_Menu_Settings_Selection]; + 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 @@ -1042,7 +1001,7 @@ func OnMenuSelection(int selection, object menuObject) return; } - if(settings[DT_Menu_Settings_InstantDescription]) + if(settings.InstantDescription.Enable) { ShowInstantDescription(columnEntries[currentColumn][selection]); } @@ -1050,7 +1009,7 @@ func OnMenuSelection(int selection, object menuObject) // update submenu column if necessary if(!multiColumnMode && selection != oldColumnSelection) { - if(entry[DT_Menu_Entry_SubMenuColumnData]) + if(entry.SubMenuInitColumnData) { SetLength(columnEntries, column + 2); @@ -1093,11 +1052,11 @@ func Refresh(array selection, bool delayed) var oldNoSelectionCallbacks = noSelectionCallbacks; noSelectionCallbacks = true; - CloseMenu(settings[DT_Menu_Settings_Object]); + CloseMenu(settings.Object); var oldRefreshing = refreshing; refreshing = true; - Create(settings, createEntries); + Create({ Settings = settings, Entries = createEntries }); refreshing = oldRefreshing; var column = BoundBy(selection[1], 0, columnCount); selection = selection[0]; @@ -1106,7 +1065,7 @@ func Refresh(array selection, bool delayed) { SelectEntry(BoundBy(selection, 0, GetLength(columnEntries[column]) - 1), column); - if(settings[DT_Menu_Settings_InstantDescription]) + if(settings.InstantDescription.Enable) { ShowInstantDescription(columnEntries[currentColumn][selection]); } @@ -1116,11 +1075,11 @@ func Refresh(array selection, bool delayed) } } -func ShowInstantDescription(array entry) +func ShowInstantDescription(map entry) { - if(entry[DT_Menu_Entry_Description]) + if(entry.Description) { - var icon = entry[DT_Menu_Entry_InstantDescriptionIcon]; + var icon = entry.InstantDescriptionIcon; var iconString; if(GetType(icon[1]) == C4V_String) { @@ -1130,8 +1089,8 @@ func ShowInstantDescription(array entry) { iconString = Format("%i:%d", icon[0] || DT_Menu_IconDummy, icon[1]); } - var pos = settings[DT_Menu_Settings_InstantDescriptionPosition]; - CustomMessage(Format("@%s", entry[DT_Menu_Entry_Description]), 0, GetOwner(settings[DT_Menu_Settings_Object]), pos[0], pos[1], 0, settings[DT_Menu_Settings_InstantDescriptionDecoration], iconString, settings[DT_Menu_Settings_InstantDescriptionFlags]); + var pos = settings.InstantDescription.Position; + CustomMessage("@" .. entry.Description, 0, GetOwner(settings.Object), pos[0], pos[1], 0, settings.InstantDescription.Decoration, iconString, settings.InstantDescription.Flags); } else { @@ -1141,91 +1100,22 @@ func ShowInstantDescription(array entry) func HideInstantDescription() { - CustomMessage("", 0, GetOwner(settings[DT_Menu_Settings_Object]), 0, 0, 0, 0, Format("%i", DT_Menu_IconDummy), settings[DT_Menu_Settings_InstantDescriptionFlags]); + CustomMessage("", 0, GetOwner(settings.Object), 0, 0, 0, 0, Format("%i", DT_Menu_IconDummy), settings.InstantDescription.Flags); } // ---------------------------------------------------------------------------- -global func Menu__Setting(array setting) { return [DT_Menu_Type_Setting, setting]; } - -global func Menu_Icon(id icon) { return Menu__Setting([DT_Menu_Settings_Icon, icon]); } -global func Menu_Object(object obj) { return Menu__Setting([DT_Menu_Settings_Object, obj]); } -global func Menu__Extra(int extra, int data) { return Menu_Combined([Menu__Setting([DT_Menu_Settings_Extra, extra]), Menu_ExtraData(data)]); } -global func Menu_Size(int width, int height) { return Menu__Setting([DT_Menu_Settings_Size, [width, height]]); } -global func Menu_ExtraData(int data) { return Menu__Setting([DT_Menu_Settings_ExtraData, data]); } -global func Menu_Title(string title) { return Menu__Setting([DT_Menu_Settings_Title, title]); } -global func Menu_RefreshInterval(int interval) { return Menu__Setting([DT_Menu_Settings_RefreshInterval, interval + !interval]); } -global func Menu_Selection(int selection, int column) { return Menu__Setting([DT_Menu_Settings_Selection, [selection, column]]); } -global func Menu__Style(int style) { return Menu__Setting([DT_Menu_Settings_Style, style]); } -global func Menu__KeepOpen(int mode) { return Menu__Setting([DT_Menu_Settings_KeepOpen, mode]); } - -global func Menu_Extra_None() { return Menu__Extra(C4MN_Extra_None); } -global func Menu_Extra_Components() { return Menu__Extra(C4MN_Extra_Components); } -global func Menu_Extra_Value() { return Menu__Extra(C4MN_Extra_Value); } -global func Menu_Extra_MagicValue(int compare) { return Menu__Extra(C4MN_Extra_MagicValue, compare); } -global func Menu_Extra_Info() { return Menu__Extra(C4MN_Extra_Info); } -global func Menu_Extra_ComponentsMagic() { return Menu__Extra(C4MN_Extra_ComponentsMagic); } - -global func Menu_Style_Normal() { return Menu__Style(C4MN_Style_Normal); } -global func Menu_Style_Context() { return Menu__Style(C4MN_Style_Context); } -global func Menu_Style_Info() { return Menu__Style(C4MN_Style_Info); } -global func Menu_Style_Dialog() { return Menu__Style(C4MN_Style_Dialog); } -global func Menu_Style_EqualItemHeight() { return Menu__Style(C4MN_Style_EqualItemHeight); } - -global func Menu_DontKeepOpen() { return Menu__KeepOpen(DT_Menu_KeepOpen_Not); } -global func Menu_KeepOpen() { return Menu__KeepOpen(DT_Menu_KeepOpen_Keep); } -global func Menu_ForceKeepOpen() { return Menu__KeepOpen(DT_Menu_KeepOpen_Force); } -global func Menu_Refresh() { return Menu__KeepOpen(DT_Menu_KeepOpen_Refresh); } -global func Menu_RefreshContinuously(int interval) { return Menu_Combined([Menu__KeepOpen(DT_Menu_KeepOpen_RefreshContinuously), Menu_RefreshInterval(interval)]); } -global func Menu_Permanent() { return Menu__KeepOpen(DT_Menu_KeepOpen_Permanent); } - -global func Menu_ConditionAllowSelection() { return Menu__Setting([DT_Menu_Settings_ConditionAllowSelection, true]);} -global func Menu_ConditionDenySelection() { return Menu__Setting([DT_Menu_Settings_ConditionAllowSelection, false]);} - -global func Menu_Callbacks(array callbacks) { return Menu__Setting([DT_Menu_Settings_Callbacks, callbacks]); } -global func Menu_Decoration(id decoration) { return Menu__Setting([DT_Menu_Settings_Decoration, decoration]); } -global func Menu_RequireAction(string action, object target) { return Menu__Setting([DT_Menu_Settings_RequireAction, [action, target]]); } -global func Menu_KeepParentOnClose(bool dontKeep) { return Menu__Setting([DT_Menu_Settings_KeepParentOnClose, !dontKeep]); } -global func Menu_ConditionDisableMode(mode) { return Menu__Setting([DT_Menu_Settings_ConditionDisableMode, mode]);} -global func Menu_Vars(array vars) { return Menu__Setting([DT_Menu_Settings_Vars, vars]); } -global func Menu_Closable(bool notClosable) { return Menu__Setting([DT_Menu_Settings_Closable, !notClosable]); } -global func Menu_InstantDescription(bool disable) { return Menu__Setting([DT_Menu_Settings_InstantDescription, !disable]); } -global func Menu_InstantDescriptionDecoration(id decoration) { return Menu__Setting([DT_Menu_Settings_InstantDescriptionDecoration, decoration]); } -global func Menu_InstantDescriptionMessageFlags(int flags) { return Menu__Setting([DT_Menu_Settings_InstantDescriptionFlags, flags]); } -global func Menu_InstantDescriptionPosition(int x, int y) { return Menu__Setting([DT_Menu_Settings_InstantDescriptionPosition, [x, y]]); } - global func Menu_Callback(array callback, int types, array argBinding) { - 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]; + 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]; return [callback, types || Menu_CallbackType_Defaults, argBinding]; } -global func Menu_Entry_Text(string Text) { return [DT_Menu_Entry_Text, Text]; } -global func Menu_Entry_Callbacks(array Callbacks) { return [DT_Menu_Entry_Callbacks, Callbacks]; } -global func Menu_Entry_Count(int Count) { return [DT_Menu_Entry_Count, Count]; } -global func Menu_Entry_Description(string Description) { return [DT_Menu_Entry_Description, Description]; } -global func Menu_Entry_Extra(int Extra) { return [DT_Menu_Entry_Extra, Extra]; } -global func Menu_Entry_XPar1(XPar1) { return [DT_Menu_Entry_XPar1, XPar1]; } -global func Menu_Entry_XPar2(XPar2) { return [DT_Menu_Entry_XPar2, XPar2]; } -global func Menu_Entry_Args(Args) { return [DT_Menu_Entry_Args, Args]; } -global func Menu_Entry_Placeholder(bool Placeholder) { return [DT_Menu_Entry_Placeholder, Placeholder]; } -global func Menu_Entry_Icon(icon, extra, int color) -{ - if(GetType(icon) == C4V_Array) - { - return [DT_Menu_Entry_Icon, icon]; - } - else - { - return [DT_Menu_Entry_Icon, [icon, extra, color]]; - } -} -global func Menu_Entry_Condition(callback, int allowDisabledSelection) { return [DT_Menu_Entry_Condition, [callback, allowDisabledSelection]]; } global func Menu_Entry_VariableCondition(array scopedVar, compare, int disableMode, bool invert, int allowDisabledSelection) { - return Menu_Entry_Condition(BindCallback(MN7I->MenuObjectCallback("VariableCondition"), [Bind(scopedVar), Bind(compare), Bind(disableMode), Bind(invert)]), allowDisabledSelection); + return BindCallback(MN7I->MenuObjectCallback("VariableCondition"), [Bind(scopedVar), Bind(compare), Bind(disableMode), Bind(invert)]); } -global func VariableCondition(array scopedVar, compare, int disableMode, bool invert) +func VariableCondition(array scopedVar, compare, int disableMode, bool invert) { var disable = ScopedVar(scopedVar) != compare; if(invert) @@ -1237,50 +1127,76 @@ global func VariableCondition(array scopedVar, compare, int disableMode, bool in return disableMode; } else - { return Menu_ConditionReact_Show; } } -global func Menu_Entry_InstantDescriptionIcon(id icon, variation, int color) -{ - return [DT_Menu_Entry_InstantDescriptionIcon, [icon, variation, color]]; -} -global func Menu_Entry_Object(object obj) -{ - return Menu_Combined([Menu_Entry_Icon(obj), Menu_Entry_Text(GetName(obj)), Menu_Entry_Description(GetDesc(obj))]); -} -global func Menu_Entry(array settings) +/* +Menu_Entry({ + Text = <Text>, + Icon = <Icon>, + Count = <Count>, + Description = <Description, shown as a Tooltip or as InstantDescription>, + Placeholder = <May the placeholder entry be selected>: true | >false<, + InstantDescriptionIcon = [iconID, iconIndex] | [iconID, portraitName, color], + Callbacks = [<Menu_Callback()>...], + Args = <Args for Callbacks>, + Condition = { + Callback = <Callback>, + AllowDisabledSelection = >Menu_Condition_Default< | Menu_Condition_AllowSelection | Menu_Condition_DenySelection + }, + Extra = <Same as extra of AddMenuItem> >Also used internally<, + XPar1 = <Same as XPar1 of AddMenuItem> >Also used internally<, + XPar2 = <Same as XPar2 of AddMenuItem> >Also used internally<, + SubMenuInitColumnData = >Internal<: For SubMenus as columns, + SubMenuColumnEntries = >Internal<: For SubMenus as columns, + Type = >Internal<: DT_Menu_Type_Entry | DT_Menu_Type_Factory | DT_Menu_Type_Columns +}) */ + + +global func Menu_Entry(map entry) { - if(!settings) + if(!entry) + { + entry = { Placeholder = false }; + } + else { - settings = [Menu_Entry_Placeholder(false)]; + entry = Extend({ + Text = "", + Placeholder = -1 + }, entry, true); } - var namedArgs = []; - namedArgs[DT_Menu_Entry_Text] = ""; - namedArgs[DT_Menu_Entry_Placeholder] = -1; - MN7I->NamedArgs(settings, namedArgs); - if(!namedArgs[DT_Menu_Entry_Description]) + if(!entry.Description) { - namedArgs[DT_Menu_Entry_Extra] |= C4MN_Add_ForceNoDesc; + entry.Extra |= C4MN_Add_ForceNoDesc; } - return [DT_Menu_Type_Entry, namedArgs]; + entry.Type = DT_Menu_Type_Entry; + if(entry.Icon && GetType(entry.Icon) != C4V_Array) + { + if(GetType(entry.Icon) == C4V_C4Object) + { + entry.Icon = [entry.Icon, true]; + } + else + { + entry.Icon = [entry.Icon]; + } + } + return entry; } -global func Menu_SubMenu(array entrySettings, array menuEntry_Settings, bool asColumn) +global func Menu_SubMenu(map submenuSettings, bool asColumn) { - var ret = Menu_Entry(entrySettings); - ret[1][DT_Menu_Entry_Args] = [ret[1][DT_Menu_Entry_Callbacks], ret[1][DT_Menu_Entry_Args], menuEntry_Settings, asColumn]; - ret[1][DT_Menu_Entry_Callbacks] = [Menu_Callback(MN7I->MenuObjectCallback("SubmenuItemCallback"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])]; + var ret = Menu_Entry(submenuSettings.Entry); + ret.Args = [ret.Callbacks, ret.Args, submenuSettings, asColumn]; + ret.Callbacks = [Menu_Callback(MN7I->MenuObjectCallback("SubMenuItemCallback"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])]; if(asColumn) { - // [menu settings (only a few settings are used), menu entries, readily populated entries (later in HandleEntries)] - var menuData = [[], [], []]; - MN7I->UncombineAndDistinguish(menuEntry_Settings, menuData[0], menuData[1]); - ret[2] = menuData; + ret.SubMenuInitColumnData = submenuSettings; } return ret; @@ -1288,7 +1204,12 @@ global func Menu_SubMenu(array entrySettings, array menuEntry_Settings, bool asC global func Menu_Factory(array callbacks, args, array binding) { - return [DT_Menu_Type_Factory, [callbacks, args, binding || [Menu_CallbackArg_Args, Menu_CallbackArg_EntryNumber, Menu_CallbackArg_Menu]]]; + return { + Type = DT_Menu_Type_Factory, + Callbacks = callbacks, + Args = args, + Binding = binding || [Menu_CallbackArg_Args, Menu_CallbackArg_EntryNumber, Menu_CallbackArg_Menu] + }; } // Menu_Columns @@ -1299,101 +1220,62 @@ global func Menu_Factory(array callbacks, args, array binding) // ]) global func Menu_Columns(array columns) { - var preparedColunmns = CreateArray(GetLength(columns)); - - for(var i = 0; i < GetLength(columns); ++i) + for(var column in columns) { - preparedColunmns[i] = []; - - var tempSettings = []; - MN7I->UncombineAndDistinguish(columns[i], tempSettings, preparedColunmns[i]); - - if(GetLength(tempSettings) > 0) + if(column.Settings && GetLength(column.Settings) > 0) { FatalError("DT_Menu::Menu_Columns: menu settings can not appear in Menu_Columns()"); } } - return [DT_Menu_Type_Columns, preparedColunmns]; + return { + Type = DT_Menu_Type_Columns, + Columns = columns + }; } global func Menu_Text(string text, bool allowSelection) { - return Menu_Entry([Menu_Entry_Text(text), Menu_Entry_Placeholder(allowSelection)]); + return Menu_Entry({ + Text = text, + Placeholder = allowSelection + }); } global func Menu_Blank(bool allowSelection) { - return Menu_Entry([Menu_Entry_Placeholder(allowSelection)]); + return Menu_Entry({ + Placeholder = allowSelection + }); } -func DeclineAcceptBack(string text, icon, string callback, array settings) +func DeclineAcceptBack(string text, icon, string callback, map settings) { - var ret = Menu_Entry([Menu_Entry_Text(text), Menu_Combined(settings || [])]); - ret[1][DT_Menu_Entry_Args] = [ret[1][DT_Menu_Entry_Callbacks], ret[1][DT_Menu_Entry_Args]]; - ret[1][DT_Menu_Entry_Callbacks] = Menu_Entry_Callbacks([Menu_Callback(MN7I->MenuObjectCallback(callback), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_Args, Menu_CallbackArg_All])])[1]; - ExtraIcon(ret[1][DT_Menu_Entry_Text], ret[1][DT_Menu_Entry_Icon], icon); + var ret = Menu_Entry(Extend({ + Text = text, + }, settings || {}, true)); + + ret.Args = [ret.Callbacks, ret.Args]; + ret.Callbacks = [Menu_Callback(MN7I->MenuObjectCallback(callback), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_Args, Menu_CallbackArg_All])]; + ExtraIcon(ret.Text, ret.Icon, icon); return ret; } -global func Menu_Decline(array settings) +global func Menu_Decline(map settings) { return MN7I->DeclineAcceptBack("$Decline$", [MN7I, 2], "DeclineAcceptCommand", settings); } -global func Menu_Accept(array settings) +global func Menu_Accept(map settings) { return MN7I->DeclineAcceptBack("$Accept$", [MN7I, 1], "DeclineAcceptCommand", settings); } -global func Menu_Back(array settings) +global func Menu_Back(map settings) { return MN7I->DeclineAcceptBack("$Back$", [MN7I, 5], "BackCommand", settings); } -global func Menu_Adaptor_Type(int Type) { return [DT_Menu_Adaptor_Type, Type]; } -global func Menu_Adaptor_Variable(array Variable) { return [DT_Menu_Adaptor_Variable, Variable]; } -global func Menu_Adaptor_Callbacks(array Callbacks) { return [DT_Menu_Adaptor_Callbacks, Callbacks]; } -global func Menu_Adaptor_MessageBoardText(string MessageBoardText) { return [DT_Menu_Adaptor_MessageBoardText, MessageBoardText]; } -global func Menu_Adaptor_WrapAround(bool WrapAround) { return [DT_Menu_Adaptor_WrapAround, WrapAround]; } -global func Menu_Adaptor_EnumSubmenuIcon(id EnumSubmenuIcon) { return [DT_Menu_Adaptor_EnumSubmenuIcon, EnumSubmenuIcon]; } -global func Menu_Adaptor_EnumAllowUnknown(bool EnumAllowUnknown) { return [DT_Menu_Adaptor_EnumAllowUnknown, EnumAllowUnknown]; } -global func Menu_Adaptor_EnumInline(bool EnumInline) { return [DT_Menu_Adaptor_EnumInline, EnumInline]; } -global func Menu_Adaptor_EnumSubmenu(int callbackType) { return [DT_Menu_Adaptor_EnumSubmenu, callbackType]; } -global func Menu_Adaptor_EnumColumnSubmenu() { return [DT_Menu_Adaptor_EnumSubmenu, true]; } -global func Menu_Adaptor_Limits(min, max, args) -{ - return [DT_Menu_Adaptor_Limits, [min, max, args]]; -} -global func Menu_Adaptor_StepSize(int step, force) { return [DT_Menu_Adaptor_StepSize, [step, force]]; } -global func Menu_Adaptor_Enum(array enumVals, array layout, bool valuesAsSeparateLists) -{ - MN7I->AdaptorLayout(layout, enumVals, valuesAsSeparateLists); - return Menu_Combined([Menu_Adaptor_Type(Menu_AdaptorType_Enum), [DT_Menu_Adaptor_LayoutVals, [enumVals, layout]]]); -} -global func Menu_Adaptor_BitField(array fieldVals, array layout, bool valuesAsSeparateLists, bool bitPositionAsValue) -{ - MN7I->AdaptorLayout(layout, fieldVals, valuesAsSeparateLists); - if(bitPositionAsValue) - { - var valuePos = layout[Menu_Layout__ValuePos] - 1; - for(var i = 0; i < GetLength(fieldVals); ++i) - { - fieldVals[i][valuePos] = 1 << fieldVals[i][valuePos]; - } - } - return Menu_Combined([Menu_Adaptor_Type(Menu_AdaptorType_BitField), [DT_Menu_Adaptor_LayoutVals, [fieldVals, layout]]]); -} -global func Menu_Adaptor_NoEmptyString() { return [DT_Menu_Adaptor_NoEmptyString, true]; } -global func Menu_Adaptor_EnumSubmenuTitleAndText(string menuTitle, string entryText) -{ - return [DT_Menu_Adaptor_EnumSubmenuTitleAndText, [menuTitle, entryText]]; -} -global func Menu_Adaptor_Boolean() { return Menu_Adaptor_Type(Menu_AdaptorType_Boolean); } -global func Menu_Adaptor_Integer() { return Menu_Adaptor_Type(Menu_AdaptorType_Integer); } -global func Menu_Adaptor_String() { return Menu_Adaptor_Type(Menu_AdaptorType_String); } -global func Menu_Adaptor_ID() { return Menu_Adaptor_Type(Menu_AdaptorType_ID); } - func AdaptorLayout(array& layout, array& vals, bool valuesAsSeparateLists) { layout = layout || [Menu_Layout_Value | Menu_Layout_Text]; @@ -1445,28 +1327,109 @@ func AdaptorLayout(array& layout, array& vals, bool valuesAsSeparateLists) } } -global func Menu_Adaptor(array entrySettings, array adaptorSettings) +/* +Menu_Adaptor({ + Entry = { + sames as for Menu_Entry + }, + Adaptor = { + Type = Menu_AdaptorType_Boolean | Menu_AdaptorType_Integer | Menu_AdaptorType_String | Menu_AdaptorType_ID | Menu_AdaptorType_Enum | Menu_AdaptorType_BitField, + Variable = <ScopedVar> storing the value, + Callbacks = [<Menu_Callback()>...], + Args = <Args for Callbacks>, + MessageBoardText = <Text shown in front of the MessageBoard>, + Limits = [<Min>, <Max>] for Integer-Type, + StepSize = [<StepSize for increasing and decreasing>, <StepSize for MessageBoard input>] for Integer-Type, + NoEmptyString = <Disallow setting the value to an empty string for String-Type>: true | >false<, + EntryIndex = >Internal<: used for MessageBoard callbacks, + WrapAround = <Wrap around the allowed values at their limits for Integer- and Enum-Type>: true <else for Enum> | false <else for Integer>, + Enum = <only for Enum-Type>: { + Values = [<[Values according to Layout]>...], + Layout = [<[Menu_Layout_*, some can be combined with &]>...], + ValuesAsSeparateLists = <Values is a "struct of arrays" instead of "array of structs">: true | >false<, + Inline = <Always show all values inlined in the containing menu>: true | >false<, + AllowUnknown = <Are unknown values allowed for the specified var? If not, it will be overwritten.>: true | >false<, + SubMenu = <Settings specific to the optional submenu possibility>: { + On = <CallbackType when to show>: >Menu_CallbackType_Special2< | true to show as extra column | Menu_CallbackType_None <to disable> | Menu_CallbackType_*, + Icon = <Icon to use for the SubMenu-Header>, + Title = <Title to use for the SubMenu-Header>, + Text = <Text to use for the individual Entries>, + } + }, + BitField = <only for BitField-Type>: { + Values = [<[Values according to Layout]>...], + Layout = [<[Menu_Layout_*, some can be combined with &]>...], + ValuesAsSeparateLists = <Values is a "struct of arrays" instead of "array of structs">: true | >false<, + BitPositionAsValue = <Instead of the values being a bit-mask, the values denote the bit-position>: true | >false<, + Mask = >Internal< + } + } +}) */ + +global func Menu_Adaptor(map settings) { - var adaptorArgs = []; - adaptorArgs[DT_Menu_Adaptor_WrapAround] = -1; - adaptorArgs[DT_Menu_Adaptor_EnumSubmenu] = Menu_CallbackType_Special2; + if(!settings.Adaptor.Type) + { + if(settings.Adaptor.Enum) + { + settings.Adaptor.Type = Menu_AdaptorType_Enum; + } + else if(settings.Adaptor.BitField) + { + settings.Adaptor.Type = Menu_AdaptorType_BitField; + } + else + { + FatalError("Menu_Adaptor: Adaptor.Type is missing!"); + } + } - MN7I->NamedArgs(adaptorSettings, adaptorArgs); + settings = Extend({ + Adaptor = { + WrapAround = -1, + Enum = { + SubMenu = { + On = Menu_CallbackType_Special2, + } + } + } + }, settings, true); - if(adaptorArgs[DT_Menu_Adaptor_WrapAround] == -1) + if(settings.Adaptor.WrapAround == -1) { - if(adaptorArgs[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Integer) + if(settings.Adaptor.Type == Menu_AdaptorType_Integer) + { + settings.Adaptor.WrapAround = false; + } + else if(settings.Adaptor.Type == Menu_AdaptorType_Enum) { - adaptorArgs[DT_Menu_Adaptor_WrapAround] = false; + settings.Adaptor.WrapAround = true; } - else if(adaptorArgs[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Enum) + } + + if(settings.Adaptor.Type == Menu_AdaptorType_BitField) + { + var layout = settings.Adaptor.BitField.Layout; + var fieldVals = settings.Adaptor.BitField.Values; + MN7I->AdaptorLayout(layout, fieldVals, settings.Adaptor.BitField.ValuesAsSeparateLists); + if(settings.Adaptor.BitField.BitPositionAsValue) { - adaptorArgs[DT_Menu_Adaptor_WrapAround] = true; + var valuePos = layout[Menu_Layout__ValuePos] - 1; + for(var i = 0; i < GetLength(fieldVals); ++i) + { + fieldVals[i][valuePos] = 1 << fieldVals[i][valuePos]; + } } + settings.Adaptor.BitField.Values = fieldVals; + settings.Adaptor.BitField.Layout = layout; + } + else if(settings.Adaptor.Type == Menu_AdaptorType_Enum) + { + MN7I->AdaptorLayout(settings.Adaptor.Enum.Layout, settings.Adaptor.Enum.Values, settings.Adaptor.Enum.ValuesAsSeparateLists); } - return Menu_Factory([MN7I->MenuObjectCallback("AdaptorFactory")], [Menu_Entry(entrySettings)[1], adaptorArgs, entrySettings], [Menu_CallbackArg_Args, Menu_CallbackArg_EntryNumber, Menu_CallbackArg_EntryColumn]); + return Menu_Factory([MN7I->MenuObjectCallback("AdaptorFactory")], [Menu_Entry(settings.Entry), settings], [Menu_CallbackArg_Args, Menu_CallbackArg_EntryNumber, Menu_CallbackArg_EntryColumn]); } func EnumValPos(array enumVals, array layout, val, bool allowUnknown) @@ -1516,13 +1479,12 @@ func ExtraIcon(string& text, &icon, extraIcon) } } -func EnumEntrySettings(string& text, &icon, string& description, int index, array args, array entry) +func EnumEntrySettings(string& text, &icon, string& description, int index, map args, map entry) { - var layoutVals = args[DT_Menu_Adaptor_LayoutVals]; - var layout = layoutVals[1]; - layoutVals = layoutVals[0]; + var layoutVals = args.Enum.Values; + var layout = args.Enum.Layout; - text = entry[DT_Menu_Entry_Text]; + text = entry.Text; if(layout[Menu_Layout__TextPos]) { text = Format(text, layoutVals[index][layout[Menu_Layout__TextPos] - 1]); @@ -1566,32 +1528,32 @@ func AdaptorFactory(args, int entryIndex, int entryColumn) { var origArgs = args; var entry = args[0]; - var entrySettings = args[2]; - args = args[1]; - var text = entry[DT_Menu_Entry_Text]; - var description = entry[DT_Menu_Entry_Description]; - var icon = entry[DT_Menu_Entry_Icon]; - var val = ScopedVar(args[DT_Menu_Adaptor_Variable]); + var entrySettings = args[1].Entry; + args = args[1].Adaptor; + var text = entry.Text; + var description = entry.Description; + var icon = entry.Icon; + var val = ScopedVar(args.Variable); var defaultMsgboardText = "$EnterValue$"; - var retSubmenu; + var retSubMenu; - args[DT_Menu_Adaptor_Args] = entry[DT_Menu_Entry_Args]; - args[DT_Menu_Adaptor_EntryIndex] = [entryIndex, entryColumn]; - args[DT_Menu_Adaptor_Callbacks] = args[DT_Menu_Adaptor_Callbacks] || []; - if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Boolean) + args.Args = entry.Args; + args.EntryIndex = [entryIndex, entryColumn]; + args.Callbacks = args.Callbacks || []; + if(args.Type == Menu_AdaptorType_Boolean) { BooleanToggleText(val, text, icon); } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_String) + else if(args.Type == Menu_AdaptorType_String) { - text = Format(entry[DT_Menu_Entry_Text], val); + text = Format(entry.Text, val); defaultMsgboardText = "$EnterText$"; } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Integer) + else if(args.Type == Menu_AdaptorType_Integer) { - var limits = AdaptorGetLimits(args[DT_Menu_Adaptor_Limits]), max, min; - var wrapAround = args[DT_Menu_Adaptor_WrapAround]; + var limits = AdaptorGetLimits(args.Limits), max, min; + var wrapAround = args.WrapAround; if(limits && !wrapAround) { if(val >= limits[1]) @@ -1603,37 +1565,36 @@ func AdaptorFactory(args, int entryIndex, int entryColumn) min = true; } } - text = Format(entry[DT_Menu_Entry_Text], val) .. " " .. ["{{MN7I:4}}", "<c 808080>{{MN7I:4}}</c>"][min]; + text = Format(entry.Text, val) .. " " .. ["{{MN7I:4}}", "<c 808080>{{MN7I:4}}</c>"][min]; ExtraIcon(text, icon, [MN7I, 3, max && RGB(128, 128, 128)]); defaultMsgboardText = "$EnterNumber$"; } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_ID) + else if(args.Type == Menu_AdaptorType_ID) { - text = Format(entry[DT_Menu_Entry_Text], val && GetName(0, val) || ""); + text = Format(entry.Text, val && GetName(0, val) || ""); if(val) { ExtraIcon(text, icon, val); } defaultMsgboardText = "$EnterIDOrName$"; } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Enum) + else if(args.Type == Menu_AdaptorType_Enum) { - if(args[DT_Menu_Adaptor_EnumInline]) + if(args.Enum.Inline) { - return AdaptorEnumSubmenuFactory([args, entry]); + return AdaptorEnumSubMenuFactory([args, entry]); } - var layoutVals = args[DT_Menu_Adaptor_LayoutVals]; - var layout = layoutVals[1]; - layoutVals = layoutVals[0]; + var layoutVals = args.Enum.Values; + var layout = args.Enum.Layout; - var index = EnumValPos(layoutVals, layout, val, args[DT_Menu_Adaptor_EnumAllowUnknown]); + var index = EnumValPos(layoutVals, layout, val, args.Enum.AllowUnknown); if(index == -1) { - if(!args[DT_Menu_Adaptor_EnumAllowUnknown]) + if(!args.Enum.AllowUnknown) { - ScopedVar(args[DT_Menu_Adaptor_Variable]) = layoutVals[0][layout[Menu_Layout__ValuePos] - 1]; + ScopedVar(args.Variable) = layoutVals[0][layout[Menu_Layout__ValuePos] - 1]; } index = 0; } @@ -1642,66 +1603,69 @@ func AdaptorFactory(args, int entryIndex, int entryColumn) EnumEntrySettings(text, icon, description, index, args, entry); - if(args[DT_Menu_Adaptor_EnumSubmenu] != Menu_CallbackType_None) + if(args.Enum.SubMenu.On != Menu_CallbackType_None) { - args[DT_Menu_Adaptor_MessageBoardText] = args[DT_Menu_Adaptor_MessageBoardText] || defaultMsgboardText; + args.MessageBoardText = args.MessageBoardText || defaultMsgboardText; - retSubmenu = [Menu_Factory([MenuObjectCallback("AdaptorEnumSubmenuFactory")], [args, entry])]; + retSubMenu = [Menu_Factory([MenuObjectCallback("AdaptorEnumSubMenuFactory")], origArgs[1])]; } } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_BitField) + else if(args.Type == Menu_AdaptorType_BitField) { return AdaptorBitFieldItemsFactory(origArgs); } - args[DT_Menu_Adaptor_MessageBoardText] = args[DT_Menu_Adaptor_MessageBoardText] || defaultMsgboardText; - if(!retSubmenu) + args.MessageBoardText = args.MessageBoardText || defaultMsgboardText; + if(!retSubMenu) { - return [Menu_Entry([Menu_Combined(entrySettings), Menu_Entry_Text(text), Menu_Entry_Callbacks([Menu_Callback(MenuObjectCallback("AdaptorCommand"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])]), Menu_Entry_Icon(icon), Menu_Entry_Description(description), Menu_Entry_Args(args)])]; + return [Menu_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))]; } else { - return [Menu_SubMenu([Menu_Combined(entrySettings), Menu_Entry_Text(text), Menu_Entry_Callbacks([Menu_Callback(MenuObjectCallback("AdaptorCommand"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])]), Menu_Entry_Icon(icon), Menu_Entry_Description(description), Menu_Entry_Args(args)], retSubmenu, GetType(args[DT_Menu_Adaptor_EnumSubmenu]) == C4V_Bool)]; + 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)]; } } -func AdaptorEnumSubmenuFactory(array args) +func AdaptorEnumSubMenuFactory(map args) { - var entry = args[1]; - args = args[0]; - var layoutVals = args[DT_Menu_Adaptor_LayoutVals]; - var layout = layoutVals[1]; - layoutVals = layoutVals[0]; + var entry = args.Entry; + args = args.Adaptor; + var layoutVals = args.Enum.Values; + var layout = args.Enum.Layout; - var submenuTitleAndText = args[DT_Menu_Adaptor_EnumSubmenuTitleAndText]; var submenuIcon = []; - if(submenuTitleAndText && submenuTitleAndText[0]) + if(args.Enum.SubMenu.Title) { - entry[DT_Menu_Entry_Text] = submenuTitleAndText[0]; + entry.Text = args.Enum.SubMenu.Title; } - var index = EnumValPos(layoutVals, layout, ScopedVar(args[DT_Menu_Adaptor_Variable]), args[DT_Menu_Adaptor_EnumAllowUnknown]); + var index = EnumValPos(layoutVals, layout, ScopedVar(args.Variable), args.Enum.AllowUnknown); var title, icon, description; EnumEntrySettings(title, icon, description, index, args, entry); var ret; - if(args[DT_Menu_Adaptor_EnumInline]) + if(args.Enum.Inline) { - ret = []; + ret = { + Entries = [] + }; } else { - ret = [ - Menu_Selection(index), - Menu_KeepParentOnClose(), - Menu_DontKeepOpen(), - Menu_Title(title) - ]; + ret = { + Settings = { + Selection = [index, 0], + KeepParentOnClose = true, + KeepOpen = Menu_KeepOpen_Not, + Title = title + }, + Entries = [] + }; } - if(args[DT_Menu_Adaptor_EnumSubmenuIcon]) + if(args.Enum.SubMenu.Icon) { - submenuIcon = [args[DT_Menu_Adaptor_EnumSubmenuIcon]]; + submenuIcon = [args.Enum.SubMenu.Icon]; } else if(icon && GetType(icon[0]) == C4V_C4ID) { @@ -1710,54 +1674,58 @@ func AdaptorEnumSubmenuFactory(array args) if(submenuIcon && GetType(submenuIcon[0]) == C4V_C4ID) { - ret[] = Menu_Icon(submenuIcon[0]); + ret.Settings.Icon = submenuIcon[0]; } var text; - var submenuTitleAndText = args[DT_Menu_Adaptor_EnumSubmenuTitleAndText]; - if(submenuTitleAndText && submenuTitleAndText[1]) + if(args.Enum.SubMenu.Text) { - entry[DT_Menu_Entry_Text] = submenuTitleAndText[1]; + entry.Text = args.Enum.SubMenu.Text; } for(var i = 0; i < GetLength(layoutVals); ++i) { icon = 0; EnumEntrySettings(text, icon, description, i, args, entry); - if(args[DT_Menu_Adaptor_EnumInline]) + if(args.Enum.Inline) { BooleanToggleText(i == index, text, icon); } - ret[] = Menu_Entry([Menu_Entry_Text(text), Menu_Entry_Icon(icon), Menu_Entry_Description(description), Menu_Entry_Callbacks([Menu_Callback(MenuObjectCallback("AdaptorEnumSubmenuItem"), Menu_CallbackType_Defaults, [Menu_CallbackArg_Args, Menu_CallbackArg_All])]), Menu_Entry_Args([i, args])]); + ret.Entries[] = Menu_Entry({ + Text = text, + Icon = icon, + Description = description, + Callbacks = [Menu_Callback(MenuObjectCallback("AdaptorEnumSubMenuItem"), Menu_CallbackType_Defaults, [Menu_CallbackArg_Args, Menu_CallbackArg_All])], + Args = [i, args] + }); } return ret; } -func AdaptorEnumSubmenuItem(args, array allArgs) +func AdaptorEnumSubMenuItem(args, array allArgs) { var index = args[0]; args = args[1]; - var val = ScopedVar(args[DT_Menu_Adaptor_Variable]); + var val = ScopedVar(args.Variable); var oldVal = val; - var enumVals = args[DT_Menu_Adaptor_LayoutVals]; - var layout = enumVals[1]; - enumVals = enumVals[0]; + var enumVals = args.Enum.Values; + var layout = args.Enum.Layout; - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val = enumVals[index][layout[Menu_Layout__ValuePos] - 1]; + ScopedVar(args.Variable) = val = enumVals[index][layout[Menu_Layout__ValuePos] - 1]; - allArgs[Menu_CallbackArg_Args] = args[DT_Menu_Adaptor_Args]; - allArgs[Menu_CallbackArg_FromSubmenu] = true; + allArgs[Menu_CallbackArg_Args] = args.Args; + allArgs[Menu_CallbackArg_FromSubMenu] = true; - var reaction = AdaptorCommandCallChangedCallback(args[DT_Menu_Adaptor_Callbacks], val, oldVal, allArgs); + var reaction = AdaptorCommandCallChangedCallback(args.Callbacks, val, oldVal, allArgs); if(reaction != Menu_React_None) { return reaction; } - if(args[DT_Menu_Adaptor_EnumInline]) + if(args.Enum.Inline) { return Menu_React_Refresh; } @@ -1768,30 +1736,29 @@ func AdaptorEnumSubmenuItem(args, array allArgs) func AdaptorBitFieldItemsFactory(args) { var entry = args[0]; - var entrySettings = args[2]; - args = args[1]; + var entrySettings = args[1].Entry; + args = args[1].Adaptor; - var text = entry[DT_Menu_Entry_Text]; - var description = entry[DT_Menu_Entry_Description]; - var icon = entry[DT_Menu_Entry_Icon]; - var fieldValue = ScopedVar(args[DT_Menu_Adaptor_Variable]); - - var layoutVals = args[DT_Menu_Adaptor_LayoutVals]; - var layout = layoutVals[1]; - layoutVals = layoutVals[0]; + var text = entry.Text; + var description = entry.Description; + var icon = entry.Icon; + var fieldValue = ScopedVar(args.Variable); + + var layoutVals = args.BitField.Values; + var layout = args.BitField.Layout; var ret = []; for(var val in layoutVals) { var mask = val[layout[Menu_Layout__ValuePos] - 1]; - text = entry[DT_Menu_Entry_Text] || "%s"; + text = entry.Text || "%s"; if(layout[Menu_Layout__TextPos]) { text = Format(text, val[layout[Menu_Layout__TextPos] - 1]); } - icon = entry[DT_Menu_Entry_Icon]; + icon = entry.Icon; BooleanToggleText((fieldValue & mask) == mask, text, icon); if(layout[Menu_Layout_Icon]) { @@ -1803,12 +1770,12 @@ func AdaptorBitFieldItemsFactory(args) description = Format(description, val[layout[Menu_Layout_Description] - 1]); } - args[DT_Menu_Adaptor_Mask] = mask; + args.BitField.Mask = mask; - ret[] = Menu_Entry([Menu_Combined(entrySettings), Menu_Entry_Text(text), Menu_Entry_Callbacks([Menu_Callback(MenuObjectCallback("AdaptorCommand"), Menu_CallbackType_All, [Menu_CallbackArg_Action, Menu_CallbackArg_MenuObject, Menu_CallbackArg_Args, Menu_CallbackArg_All])]), Menu_Entry_Icon(icon), Menu_Entry_Description(description), Menu_Entry_Args(args)]); + ret[] = Menu_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)); } - return ret; + return { Entries = ret }; } func WrapOrBind(int val, array limits, bool wrap) @@ -1860,24 +1827,24 @@ func AdaptorCommandCallChangedCallback(callbacks, val, oldVal, array allArgs) func AdaptorCommand(int action, object obj, args, array allArgs) { - var val = ScopedVar(args[DT_Menu_Adaptor_Variable]); + var val = ScopedVar(args.Variable); var oldVal = val; - allArgs[Menu_CallbackArg_Args] = args[DT_Menu_Adaptor_Args]; + allArgs[Menu_CallbackArg_Args] = args.Args; - var reaction = CallCallbacks(args[DT_Menu_Adaptor_Callbacks], action, allArgs, Menu_React_Refresh, true); + var reaction = CallCallbacks(args.Callbacks, action, allArgs, Menu_React_Refresh, true); if(reaction != Menu_React_Refresh) { return reaction; } - if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Boolean) + if(args.Type == Menu_AdaptorType_Boolean) { if(action & (Menu_CallbackType_Normal | Menu_CallbackType_Special2)) { - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val = !val; - reaction = AdaptorCommandCallChangedCallback(args[DT_Menu_Adaptor_Callbacks], val, oldVal, allArgs); + ScopedVar(args.Variable) = val = !val; + reaction = AdaptorCommandCallChangedCallback(args.Callbacks, val, oldVal, allArgs); if(reaction != Menu_React_None) { return reaction; @@ -1888,11 +1855,11 @@ func AdaptorCommand(int action, object obj, args, array allArgs) return Menu_React_KeepOpen; } } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Integer) + else if(args.Type == Menu_AdaptorType_Integer) { - var limits = AdaptorGetLimits(args[DT_Menu_Adaptor_Limits]); - var wrapAround = args[DT_Menu_Adaptor_WrapAround]; - var step = args[DT_Menu_Adaptor_StepSize]; + var limits = AdaptorGetLimits(args.Limits); + var wrapAround = args.WrapAround; + var step = args.StepSize; var stepSize = 1; if(step) { @@ -1903,8 +1870,8 @@ func AdaptorCommand(int action, object obj, args, array allArgs) if(msgBoardMode == 0) { msgBoardMode = Menu_AdaptorType_Integer + 1; - msgBoardEntry = args[DT_Menu_Adaptor_EntryIndex]; - CallMessageBoard(this, false, args[DT_Menu_Adaptor_MessageBoardText], GetOwner(obj)); + msgBoardEntry = args.EntryIndex; + CallMessageBoard(this, false, args.MessageBoardText, GetOwner(obj)); } return Menu_React_KeepOpen; } @@ -1925,8 +1892,8 @@ func AdaptorCommand(int action, object obj, args, array allArgs) if(val != oldVal) { - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val; - reaction = AdaptorCommandCallChangedCallback(args[DT_Menu_Adaptor_Callbacks], val, oldVal, allArgs); + ScopedVar(args.Variable) = val; + reaction = AdaptorCommandCallChangedCallback(args.Callbacks, val, oldVal, allArgs); if(reaction != Menu_React_None) { return reaction; @@ -1937,15 +1904,15 @@ func AdaptorCommand(int action, object obj, args, array allArgs) return Menu_React_KeepOpen; } } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_String) + else if(args.Type == Menu_AdaptorType_String) { if(action & (Menu_CallbackType_Normal | Menu_CallbackType_Special2)) { if(msgBoardMode == 0) { msgBoardMode = Menu_AdaptorType_String + 1; - msgBoardEntry = args[DT_Menu_Adaptor_EntryIndex]; - CallMessageBoard(this, false, args[DT_Menu_Adaptor_MessageBoardText], GetOwner(obj)); + msgBoardEntry = args.EntryIndex; + CallMessageBoard(this, false, args.MessageBoardText, GetOwner(obj)); } } if(action == Menu_CallbackType_Close) @@ -1957,43 +1924,42 @@ func AdaptorCommand(int action, object obj, args, array allArgs) return Menu_React_KeepOpen; } } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_ID) + else if(args.Type == Menu_AdaptorType_ID) { if(action & (Menu_CallbackType_Normal | Menu_CallbackType_Special2)) { if(msgBoardMode == 0) { msgBoardMode = Menu_AdaptorType_ID + 1; - msgBoardEntry = args[DT_Menu_Adaptor_EntryIndex]; - CallMessageBoard(this, false, args[DT_Menu_Adaptor_MessageBoardText], GetOwner(obj)); + msgBoardEntry = args.EntryIndex; + CallMessageBoard(this, false, args.MessageBoardText, GetOwner(obj)); } } return Menu_React_KeepOpen; } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_Enum) + else if(args.Type == Menu_AdaptorType_Enum) { - if(GetType(args[DT_Menu_Adaptor_EnumSubmenu]) == C4V_Bool) + if(GetType(args.Enum.SubMenu.On) == C4V_Bool) { if(action & Menu_CallbackType_Defaults) { - return Menu_React_ShowSubmenu; + return Menu_React_ShowSubMenu; } else { return Menu_React_None; } } - else if(args[DT_Menu_Adaptor_EnumSubmenu] & action) + else if(args.Enum.SubMenu.On & action) { - return Menu_React_ShowSubmenu; + return Menu_React_ShowSubMenu; } - var enumVals = args[DT_Menu_Adaptor_LayoutVals]; - var layout = enumVals[1]; - enumVals = enumVals[0]; + var enumVals = args.Enum.Values; + var layout = args.Enum.Layout; - var index = EnumValPos(enumVals, layout, val, args[DT_Menu_Adaptor_EnumAllowUnknown]); - var wrapAround = args[DT_Menu_Adaptor_WrapAround]; + var index = EnumValPos(enumVals, layout, val, args.Enum.AllowUnknown); + var wrapAround = args.WrapAround; if(action & (Menu_CallbackType_Normal | Menu_CallbackType_Special2)) { @@ -2010,18 +1976,18 @@ func AdaptorCommand(int action, object obj, args, array allArgs) index = WrapOrBind(index, [0, GetLength(enumVals) - 1], wrapAround); - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val = enumVals[index][layout[Menu_Layout__ValuePos] - 1]; - reaction = AdaptorCommandCallChangedCallback(args[DT_Menu_Adaptor_Callbacks], val, oldVal, allArgs); + ScopedVar(args.Variable) = val = enumVals[index][layout[Menu_Layout__ValuePos] - 1]; + reaction = AdaptorCommandCallChangedCallback(args.Callbacks, val, oldVal, allArgs); if(reaction != Menu_React_None) { return reaction; } } - else if(args[DT_Menu_Adaptor_Type] == Menu_AdaptorType_BitField) + else if(args.Type == Menu_AdaptorType_BitField) { if(action & (Menu_CallbackType_Normal | Menu_CallbackType_Special2)) { - var mask = args[DT_Menu_Adaptor_Mask]; + var mask = args.BitField.Mask; if((val & mask) == mask) { val &= ~mask; @@ -2031,8 +1997,8 @@ func AdaptorCommand(int action, object obj, args, array allArgs) val |= mask; } - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val; - reaction = AdaptorCommandCallChangedCallback(args[DT_Menu_Adaptor_Callbacks], val, oldVal, allArgs); + ScopedVar(args.Variable) = val; + reaction = AdaptorCommandCallChangedCallback(args.Callbacks, val, oldVal, allArgs); if(reaction != Menu_React_None) { return reaction; @@ -2050,15 +2016,15 @@ func AdaptorCommand(int action, object obj, args, array allArgs) func InputCallback(string input, int plr) { var entry = columnEntries[msgBoardEntry[1]][msgBoardEntry[0]]; - var args = entry[DT_Menu_Entry_Args]; - var callbackArgs = args[DT_Menu_Adaptor_Args]; - var oldVal = ScopedVar(args[DT_Menu_Adaptor_Variable]); + var args = entry.Args; + var callbackArgs = args.Args; + var oldVal = ScopedVar(args.Variable); var val = input; if(msgBoardMode - 1 == Menu_AdaptorType_Integer) { var int = ParseInt(input); - var limits = AdaptorGetLimits(args[DT_Menu_Adaptor_Limits]); - var step = args[DT_Menu_Adaptor_StepSize]; + var limits = AdaptorGetLimits(args.Limits); + var step = args.StepSize; if(GetType(int) == C4V_Int || GetType(int) == C4V_Any) { if(step && step[1]) @@ -2074,7 +2040,7 @@ func InputCallback(string input, int plr) { int = BoundBy(int, limits[0], limits[1]); } - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val = int; + ScopedVar(args.Variable) = val = int; } else { @@ -2083,13 +2049,13 @@ func InputCallback(string input, int plr) } else if(msgBoardMode - 1 == Menu_AdaptorType_String) { - if(args[DT_Menu_Adaptor_NoEmptyString] && (!input || input == "")) + if(args.NoEmptyString && (!input || input == "")) { val = oldVal; } else { - ScopedVar(args[DT_Menu_Adaptor_Variable]) = input; + ScopedVar(args.Variable) = input; } } else if(msgBoardMode - 1 == Menu_AdaptorType_ID) @@ -2097,12 +2063,12 @@ func InputCallback(string input, int plr) val = GetIDByName(input); // WARNING: desyncs between clients with different languages if(!val && GetLength(input) == 4) val = C4Id(input); if(!GetName(0, val)) val = 0; - ScopedVar(args[DT_Menu_Adaptor_Variable]) = val; + ScopedVar(args.Variable) = val; } msgBoardMode = 0; if(val != oldVal) { - var reaction = CallCallbacks(args[DT_Menu_Adaptor_Callbacks], Menu_CallbackType_ValueChanged, [Menu_CallbackType_ValueChanged, entry[DT_Menu_Entry_Icon], settings[DT_Menu_Settings_Object], callbackArgs, 0, 0, val, oldVal]); + var reaction = CallCallbacks(args.Callbacks, Menu_CallbackType_ValueChanged, [Menu_CallbackType_ValueChanged, entry.Icon, settings.Object, callbackArgs, 0, 0, val, oldVal]); if(reaction != Menu_React_None) { return React(reaction, msgBoardEntry); @@ -2111,74 +2077,83 @@ func InputCallback(string input, int plr) Refresh(msgBoardEntry); } -global func Menu_Combined(array combined) { return [DT_Menu_Combined, combined]; } - -global func CreateNewMenu(array menu, inheritSettings, object parentMenu) -{ - var settings = inheritSettings; - - if(GetType(settings) != C4V_Array) settings = []; - settings[DT_Menu_Settings_Style] &= ~C4MN_Style_EqualItemHeight; // EqualItemHeight can't be inherited - settings[DT_Menu_Settings_Selection] = []; // Selection can't be inherited - settings[DT_Menu_Settings_Callbacks] = 0; // Global callbacks can't be inherited (maybe filter callbacks) - - settings[DT_Menu_Settings_Parent] = parentMenu; - - var entries = []; - - MN7I->UncombineAndDistinguish(menu, settings, entries); +/* +CreateNewMenu({ + Settings = { + Icon = <Icon>, + Title = <Title>, + Object = <Object for which the menu is shown>, + Style = <Same as Style of CreateMenu>, + Size = [<Columns>, <Rows>] passed to SetMenuSize(), + Selecion = <Initial Selection>, + KeepOpen = <Keep Open Mode>: Menu_KeepOpen_*, + RefreshInterval = <Interval in Frames> for Menu_KeepOpen_RefreshContinuously, + Callbacks = [<Menu_Callback()...>] global Callbacks, + Decoration = <Decoration ID> passed to SetMenuDecoration(), + RequireAction = [<Action Name>] | [<Action Name>, <Action Target>] required action (and target) for the Settings.Object; if not fulfilled the menu will close itself, + KeepParentOnClose = <Should the parent menu stay open when the submenu closes>: true | >false<, + Vars = [<Initial values of MenuVar() ScopedVariables>...], + Closable = <Can the menu be closed by pressing dig / clicking the X in the corner>: true | >false<, + InstantDescription = <If enabled, shows the description of an entry immediately in a separate CustomMessage()>: { + Enable = true | >false<, + Decoration = <Decoration> passed to CustomMessage(); >DT_Menu_DefaultInstantDescriptionDecoration<, + Position = [<x>, <y>] passed to CustomMessage(); >[40, -60]<, + Flags = <Flags> passed to CustomMessage(); >MSG_Left | MSG_Bottom< + }, + Extra = <Same as extra of CreateMenu>, + ExtraData = <Same as extraData of CreateMenu>, + Condition = { + DisableMode = <How to handle disabled entries>: >Menu_ConditionReact_Hide< | Menu_ConditionReact_*, + AllowSelection = <Allow disabled entries to be selected>: true | >false< + }, + Parent = >Internal<: Used for submenus + }, + Entries = + [Menu_Columns()] | + [<Menu_Entry() | Menu_Text() | Menu_Blank() | Menu_Decline() | Menu_Accept() | Menu_Back() | Menu_Adaptor() | | Menu_SubMenu() | Menu_Factory()>...] +}) */ + +global func CreateNewMenu(map settings, map inheritSettings, object parentMenu) +{ + inheritSettings = inheritSettings || {}; var menuObj = CreateObject(MN7I); - menuObj->Create(settings, entries); - - return menuObj; -} - -func NamedArg(array namedArg, array &args) -{ - args[namedArg[0]] = namedArg[1]; -} - -func UncombineAndDistinguish(array combined, array &settings, array &entries) -{ - for(var val in combined) - { - if(val[0] == DT_Menu_Type_Setting) + settings = Extend(Extend(Extend( { - if((val[1][0] == DT_Menu_Settings_Style && val[1][1] == C4MN_Style_EqualItemHeight) || settings[DT_Menu_Settings_Style] == C4MN_Style_EqualItemHeight) - { - settings[DT_Menu_Settings_Style] |= val[1][1]; + Settings = { + Condition = { + DisableMode = Menu_ConditionReact_Hide + }, + InstantDescription = { + Decoration = DT_Menu_DefaultInstantDescriptionDecoration, + Flags = MSG_Left | MSG_Bottom, + Position = [40, -60] + } } - else - { - NamedArg(val[1], settings); + }, { Settings = inheritSettings }, true), { + Settings = { + Selection = [], // Selection can't be inherited + Callbacks = [], // Global callbacks can't be inherited (maybe filter callbacks) + Parent = parentMenu } - } - else if(val[0] == DT_Menu_Type_Entry || val[0] == DT_Menu_Type_Factory || val[0] == DT_Menu_Type_Columns) - { - entries[] = val; - } - else if(val[0] == DT_Menu_Combined) - { - UncombineAndDistinguish(val[1], settings, entries); - } + }, true), + settings, true); + + if(GetType(settings.Settings.Selection) == C4V_Int) + { + settings.Settings.Selection = [settings.Settings.Selection, 0]; } -} -func NamedArgs(array namedArgs, array& args) -{ - for(var arg in namedArgs) + if(inheritSettings.Style) { - if(arg[0] == DT_Menu_Combined) - { - NamedArgs(arg[1], args); - } - else - { - NamedArg(arg, args); - } + // EqualItemHeight can't be inherited + settings.Settings.Style &= ~C4MN_Style_EqualItemHeight; } + + menuObj->Create(settings); + + return menuObj; } func DeclineAcceptBackCommand(int action, args, int defaultAction, array allArgs) @@ -2294,7 +2269,7 @@ func GetSelection(int mode) func GetObject() { - return settings[DT_Menu_Settings_Object]; + return settings.Object; } func CreateIconDummy() @@ -2306,22 +2281,3 @@ func CreateIconDummy() // Symbol -> Icon static const Menu_Layout_Symbol = Menu_Layout_Icon; static const Menu_CallbackArg_Symbol = Menu_CallbackArg_Icon; - -global func Menu_Symbol() { return Menu_Icon(...); } -global func Menu_Entry_Symbol() { return Menu_Entry_Icon(...); } - -// InfoCaption -> Description -static const Menu_Layout_InfoCaption = Menu_Layout_Description; - -global func Menu_Entry_InfoCaption() { return Menu_Entry_Description(...); } - -// Menu_Caption -> Menu_Title -global func Menu_Caption() { return Menu_Title(...); } - -// Menu_Entry_Caption -> Menu_Entry_Text -static const Menu_Layout_Caption = Menu_Layout_Text; - -global func Menu_Entry_Caption() { return Menu_Entry_Text(...); } - -// Menu_Adaptor_EnumSubmenuCaption -> Menu_Adaptor_EnumSubmenuTitleAndText -global func Menu_Adaptor_EnumSubmenuCaption() { return Menu_Adaptor_EnumSubmenuTitleAndText(...); } |
