diff options
author | Markus Mittendrein <git@maxmitti.tk> | 2018-11-07 23:52:08 +0100 |
---|---|---|
committer | Markus Mittendrein <git@maxmitti.tk> | 2018-11-07 23:52:08 +0100 |
commit | e8cf85636f2a4fcf1cc41fc5f56f9b90bbb013ec (patch) | |
tree | ae68f772c7e22a256f0adb57372d107aa1daf62b | |
parent | 91056c65c208eb85fa9d860a21c0cf823fb82a62 (diff) | |
download | DTMenuDebug.c4d-e8cf85636f2a4fcf1cc41fc5f56f9b90bbb013ec.tar.gz DTMenuDebug.c4d-e8cf85636f2a4fcf1cc41fc5f56f9b90bbb013ec.zip |
Add Menu_Columns()
Allow specifying a column in Menu_Selection() (the column is ignored in column submenus)
Fix Graphics
Don't let nested factories overwrite their parents factories' args
Update InstantDescription in Refresh()
Clean up and fix Refresh() a bit
-rw-r--r-- | Graphics.png | bin | 13307 -> 13698 bytes | |||
-rw-r--r-- | Script.c | 219 |
2 files changed, 154 insertions, 65 deletions
diff --git a/Graphics.png b/Graphics.png Binary files differindex 4b53b19..a9ad684 100644 --- a/Graphics.png +++ b/Graphics.png @@ -41,6 +41,7 @@ static const DT_Menu_KeepOpen_Refresh_Mask = 0x18; // DT_Menu_KeepOpen_Refresh | 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 DT_Menu_Action_Normal = 0; static const DT_Menu_Action_Special2 = 1; @@ -169,7 +170,6 @@ static const Menu_Layout__NoFlagMask = 3; local settings; local createEntries; -local entryCount; local currentColumn; local columnCount; local columnEntries; @@ -181,13 +181,14 @@ local refreshing; local msgBoardMode; local msgBoardEntry; local noSelectionCallbacks; +local multiColumnMode; local subMenu; local vars; func Initialize() { currentColumnSelections = [-1]; - columnEntries = [[]]; + columnEntries = []; msgBoardEntry = []; vars = []; } @@ -209,7 +210,7 @@ func Create(array cSettings, array cEntries) settings[DT_Menu_Settings_InstantDescriptionPosition] = [40, -60]; } - entryCount = 0; + multiColumnMode = false; columnCount = 0; columnOffsets = []; @@ -231,7 +232,9 @@ func Create(array cSettings, array cEntries) factoryArgs[Menu_CallbackArg_Menu] = this; factoryArgs[Menu_CallbackArg_MenuObject] = settings[DT_Menu_Settings_Object]; - HandleEntries(createEntries, entryCount, columnEntries[0], settings, factoryArgs, 0); + var index = 0; + columnEntries[0] = []; + HandleEntries(createEntries, index, columnEntries[0], settings, factoryArgs, 0, true); if(columnCount > 1 && settings[DT_Menu_Settings_Style] != C4MN_Style_Context) { @@ -242,38 +245,42 @@ func Create(array cSettings, array cEntries) if(!(settings[DT_Menu_Settings_Object])) { FatalError("Assertion failed: CreateNewMenu: menu object is missing; assertion code: settings[DT_Menu_Settings_Object]"); } var title = settings[DT_Menu_Settings_Title]; - var submenuTitle; - // update submenu columns if necessary and build title - for(var i = 0; i < GetLength(currentColumnSelections); ++i) - { - // TODO: cascade? then remove the columnSelection == -1 check - var columnSelection = currentColumnSelections[i]; - if((columnSelection == -1) || !columnEntries[i]) - { - break; - } - var submenuData = columnEntries[i][columnSelection][DT_Menu_Entry_SubMenuColumnData]; - if(submenuData) + if(!multiColumnMode) + { + var submenuTitle; + // update submenu columns if necessary and build title + for(var i = 0; i < GetLength(currentColumnSelections); ++i) { - columnEntries[i + 1] = submenuData[2]; - - var submenuSettings = submenuData[0]; - /*var */submenuTitle = submenuSettings[DT_Menu_Settings_Title] || ""; - if(submenuSettings[DT_Menu_Settings_Icon]) + // TODO: cascade? then remove the columnSelection == -1 check + var columnSelection = currentColumnSelections[i]; + if((columnSelection == -1) || !columnEntries[i]) { - submenuTitle = Format("{{%i}} %s", submenuSettings[DT_Menu_Settings_Icon], submenuTitle); + break; } - // 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:6}} %s", title, submenuTitle); + var submenuData = columnEntries[i][columnSelection][DT_Menu_Entry_SubMenuColumnData]; + if(submenuData) + { + columnEntries[i + 1] = submenuData[2]; + + var submenuSettings = submenuData[0]; + /*var */submenuTitle = submenuSettings[DT_Menu_Settings_Title] || ""; + if(submenuSettings[DT_Menu_Settings_Icon]) + { + submenuTitle = Format("{{%i}} %s", submenuSettings[DT_Menu_Settings_Icon], submenuTitle); + } + + // 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); + } } - } - if(submenuTitle) - { - title = Format("... {{MN7I:6}} %s", submenuTitle); + if(submenuTitle) + { + title = Format("... {{MN7I:7}} %s", submenuTitle); + } } 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); @@ -281,11 +288,11 @@ func Create(array cSettings, array cEntries) AddEntries(); - if(entryCount > 0) + if(GetLength(columnEntries[0]) > 0) { if(!refreshing) { - SelectEntry(settings[DT_Menu_Settings_Selection]); + SelectEntry(settings[DT_Menu_Settings_Selection][0], settings[DT_Menu_Settings_Selection][1]); } } else @@ -303,7 +310,7 @@ func Create(array cSettings, array cEntries) func LeaveSubMenuColumn() { - if(!(currentColumn > 0)) { FatalError("Assertion failed: LeaveSubMenuColumn: currentColumn is not a submenu; can't leave; assertion code: currentColumn > 0"); } + if(!(!multiColumnMode && currentColumn > 0)) { FatalError("Assertion failed: LeaveSubMenuColumn: currentColumn is not a submenu; can't leave; assertion code: !multiColumnMode && currentColumn > 0"); } SelectEntry(currentColumnSelections[currentColumn - 1], currentColumn - 1); Refresh(GetSelection(Menu_Selection_WithColumn)); } @@ -509,7 +516,7 @@ func Suspend(bool cont) } } -func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, array& factoryArgs, int column) +func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, array& factoryArgs, int column, bool isMainColumn) { if(column >= columnCount) { @@ -520,11 +527,20 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, { if(entry[0] == 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(multiColumnMode) + { + FatalError("DT_Menu::HandleEntries: Menu_Columns() and Submenu columns can not be used together"); + } + var index = 0; - HandleEntries(entry[2][1], index, entry[2][2], entry[2][0], factoryArgs, column + 1); + HandleEntries(entry[2][1], index, entry[2][2], entry[2][0], factoryArgs, column + 1, false); entry[1][DT_Menu_Entry_SubMenuColumnData] = entry[2]; } @@ -532,10 +548,9 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, } else if(entry[0] == DT_Menu_Type_Factory) { - factoryArgs[Menu_CallbackArg_Args] = entry[1][1]; - for(var callback in entry[1][0]) { + factoryArgs[Menu_CallbackArg_Args] = entry[1][1]; factoryArgs[Menu_CallbackArg_EntryNumber] = i; factoryArgs[Menu_CallbackArg_EntryColumn] = column; var factoryResult = CallA(callback, BindCallbackArgs(factoryArgs, entry[1][2])); @@ -543,7 +558,7 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, { var newEntries = []; UncombineAndDistinguish(factoryResult, retSettings, newEntries); - HandleEntries(newEntries, i, ret, retSettings, factoryArgs); + HandleEntries(newEntries, i, ret, retSettings, factoryArgs, column, isMainColumn); } else if(factoryResult == Menu_React_Close) { @@ -555,6 +570,41 @@ func HandleEntries(array factoryEntries, int& i, array& ret, array& retSettings, } } } + else if(entry[0] == DT_Menu_Type_Columns) + { + if(multiColumnMode) + { + FatalError("DT_Menu::HandleEntries: only one Menu_Columns() can appear in the whole menu"); + } + + if(columnCount > 1) + { + FatalError("DT_Menu::HandleEntries: Menu_Columns() and Submenu columns can not be used together"); + } + + if(GetLength(columnEntries[0]) > 0) + { + FatalError("DT_Menu::HandleEntries: if Menu_Columns() is used, all entries must occur inside it"); + } + + multiColumnMode = true; + + var j = 0; + for(var columnData in entry[1]) + { + columnEntries[j] = []; + + var index = 0; + var tempSettings = []; + HandleEntries(columnData, index, columnEntries[j], settings, factoryArgs, j, false); + ++j; + + if(GetLength(tempSettings) > 0) + { + FatalError("DT_Menu::HandleEntries: menu settings can not appear in Menu_Columns()"); + } + } + } else { Log("WARNING: DT_Menu::HandleEntries: ignoring invalid Non-Entry/Factory: %v", entry); @@ -579,18 +629,21 @@ func AddEntries() SetMenuSize(columnCount, entriesCount, settings[DT_Menu_Settings_Object]); } - for(var i = 1; i < GetLength(columnEntries); ++i) + if(!multiColumnMode) { - var column = columnEntries[i]; - if(column) + for(var i = 1; i < GetLength(columnEntries); ++i) { - var offset = currentColumnSelections[i - 1] + columnOffsets[i - 1]; - var entryCount = GetLength(column); - if(offset + entryCount > entriesCount) + var column = columnEntries[i]; + if(column) { - offset = entriesCount - entryCount; + var offset = currentColumnSelections[i - 1] + columnOffsets[i - 1]; + var entryCount = GetLength(column); + if(offset + entryCount > entriesCount) + { + offset = entriesCount - entryCount; + } + columnOffsets[i] = offset; } - columnOffsets[i] = offset; } } @@ -648,8 +701,7 @@ func AddEntries() entry[DT_Menu_Entry_XPar1] = icon[1]; } } - - if(GetType(icon[0]) == C4V_C4Object) + else if(GetType(icon[0]) == C4V_C4Object) { entry[DT_Menu_Entry_Extra] |= C4MN_Add_ImgObject; entry[DT_Menu_Entry_XPar1] = icon[0]; @@ -681,7 +733,7 @@ func AddEntries() if(entry[DT_Menu_Entry_SubMenuColumnData] && currentColumnSelections[j] == rowIndex) { - text = Format("%s {{MN7I:6}}", text); + 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]); @@ -708,7 +760,7 @@ func React(reaction, array entryIndex, int refreshDelayed) } else if(reaction == Menu_React_Back) { - if(currentColumn > 0) + if(currentColumn > 0 && !multiColumnMode) { LeaveSubMenuColumn(); } @@ -728,7 +780,7 @@ func React(reaction, array entryIndex, int refreshDelayed) if(reaction[0] == Menu_React_SelectionOffset) { selection[0] += reaction[1]; - selection[0] %= entryCount; + selection[0] %= GetLength(columnEntries[currentColumn]); } else if(reaction[0] == Menu_React_SelectionChange) { @@ -790,7 +842,8 @@ func SubmenuItemCallback(int action, object menuObject, args, array allArgs) { if(args[3]) { - SelectEntry(columnEntries[currentColumn][currentColumnSelections[currentColumn]][DT_Menu_Entry_SubMenuColumnData][0][DT_Menu_Settings_Selection], currentColumn + 1); + var targetSelection = columnEntries[currentColumn][currentColumnSelections[currentColumn]][DT_Menu_Entry_SubMenuColumnData][0][DT_Menu_Settings_Selection]; + SelectEntry(targetSelection && targetSelection[0], currentColumn + 1); } else { @@ -908,6 +961,11 @@ func OnMenuSelection(int selection, object menuObject) } return; } + else if(multiColumnMode) + { + SelectEntry(GetLength(columnEntries[column]) - 1, column); + return; + } skipHandling = true; } @@ -954,11 +1012,13 @@ func OnMenuSelection(int selection, object menuObject) selection = currentColumnSelections[column]; } - if(selection + columnOffsets[currentColumn] == oldColumnOldSelection + columnOffsets[oldColumn]) + // navigating between submenu columns; not in multiColumnMode + if(!multiColumnMode && (selection + columnOffsets[currentColumn] == oldColumnOldSelection + columnOffsets[oldColumn])) { if(currentColumn == oldColumn + 1 && oldIsColumnSubmenu) { var targetSelection = columnEntries[currentColumn - 1][oldColumnOldSelection][DT_Menu_Entry_SubMenuColumnData][0][DT_Menu_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) @@ -991,7 +1051,7 @@ func OnMenuSelection(int selection, object menuObject) } // update submenu column if necessary - if(selection != oldColumnSelection) + if(!multiColumnMode && selection != oldColumnSelection) { if(entry[DT_Menu_Entry_SubMenuColumnData]) { @@ -1033,11 +1093,8 @@ func Refresh(array selection, bool delayed) } else { - var disabledCallbacks; - if(!noSelectionCallbacks) - { - disabledCallbacks = noSelectionCallbacks = true; - } + var oldNoSelectionCallbacks = noSelectionCallbacks; + noSelectionCallbacks = true; CloseMenu(settings[DT_Menu_Settings_Object]); @@ -1045,15 +1102,16 @@ func Refresh(array selection, bool delayed) refreshing = true; Create(settings, createEntries); refreshing = oldRefreshing; - var column = selection[1]; + var column = BoundBy(selection[1], 0, columnCount); selection = selection[0]; - // TODO: BoundBy for column? SelectEntry(BoundBy(selection, 0, GetLength(columnEntries[column]) - 1), column); - if(disabledCallbacks) + if(settings[DT_Menu_Settings_InstantDescription]) { - noSelectionCallbacks = false; + ShowInstantDescription(columnEntries[currentColumn][selection]); } + + noSelectionCallbacks = oldNoSelectionCallbacks; } } @@ -1096,7 +1154,7 @@ global func Menu_Size(int width, int height) { if(!(width >= 0 && height >= 0)) 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) { if(!(interval >= 0)) { FatalError("Assertion failed: Menu_RefreshInterval: Negative interval doesn't make sense; assertion code: interval >= 0"); }return Menu__Setting([DT_Menu_Settings_RefreshInterval, interval + !interval]); } -global func Menu_Selection(int selection) { return Menu__Setting([DT_Menu_Settings_Selection, selection]); } +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]); } @@ -1278,6 +1336,32 @@ 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]]]; } +// Menu_Columns +// ([ +// [ first column entries ], +// [ second column entries ], +// ... +// ]) +global func Menu_Columns(array columns) +{ + var preparedColunmns = CreateArray(GetLength(columns)); + + for(var i = 0; i < GetLength(columns); ++i) + { + preparedColunmns[i] = []; + + var tempSettings = []; + MN7I->UncombineAndDistinguish(columns[i], tempSettings, preparedColunmns[i]); + + if(GetLength(tempSettings) > 0) + { + FatalError("DT_Menu::Menu_Columns: menu settings can not appear in Menu_Columns()"); + } + } + + return [DT_Menu_Type_Columns, preparedColunmns]; +} + global func Menu_Text(string text, bool allowSelection) { return Menu_Entry([Menu_Entry_Text(text), Menu_Entry_Placeholder(allowSelection)]); @@ -2126,7 +2210,7 @@ global func CreateNewMenu(array menu, inheritSettings, object parentMenu) if(GetType(settings) != C4V_Array) settings = []; settings[DT_Menu_Settings_Style] &= ~C4MN_Style_EqualItemHeight; // EqualItemHeight can't be inherited - settings[DT_Menu_Settings_Selection] = 0; // Selection 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; @@ -2164,7 +2248,7 @@ func UncombineAndDistinguish(array combined, array &settings, array &entries) NamedArg(val[1], settings); } } - else if(val[0] == DT_Menu_Type_Entry || val[0] == DT_Menu_Type_Factory) + else if(val[0] == DT_Menu_Type_Entry || val[0] == DT_Menu_Type_Factory || val[0] == DT_Menu_Type_Columns) { entries[GetLength(entries)] = val; } @@ -2286,6 +2370,11 @@ func GetSelection(int mode) } else if(mode == Menu_Selection_SubMenuColumnChain) { + if(multiColumnMode) + { + FatalError("DT_Menu::GetSelection: Menu_Selection_SubMenuColumnChain doesn't make sense when Menu_Columns() are used"); + } + var ret = []; for(var i = 0; i < columnEntries; ++i) |