-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLoader.cs
195 lines (179 loc) · 8.41 KB
/
Loader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Max;
namespace ADNMenuSample
{
/// <summary>
/// Public managed c# class to load assembly
/// </summary>
public static class Loader
{
/// <summary>
/// Init point for assembly loader
/// </summary>
public static void AssemblyMain()
{
MenuUtilities.SetupMenuHandlers();
}
}
/// <summary>
/// Utilitiy class to handle menus at global level.
/// </summary>
public class MenuUtilities
{
static IActionItem m_mouseAction;
static IActionItem m_builtinVpConfigAction;
/// <summary>
/// Note, this method is iterating all action tbales and actions (for this example to also be able to find built-in actions).
/// Normally, if you only need your own, you can use actionManager.FindTable(context); but when using the
/// CuiActionCommandAdapter, the context is not available, so this method is still the best option.
/// To find only your actions, if you make all your CuiActionCommandAdapter actions use the same category(s),
/// then you can use the table name to find your table (category), then iterate just your the commands.
/// </summary>
static void LookupActions()
{
var actionManager = GlobalInterface.Instance.COREInterface.ActionManager;
//actionManager.FindTable();
for (var actionTableIndex = 0; actionTableIndex < actionManager.NumActionTables; ++actionTableIndex)
{
var actionTable = actionManager.GetTable(actionTableIndex);
//actionTable.
for (var actionIndex = 0; actionIndex < actionTable.Count; ++actionIndex)
{
var action = actionTable[actionIndex];
// finds our known cui action.
if (action != null && action.DescriptionText == AdnMenuSampleStrings.actionText01)
{
m_mouseAction = action;
uint n = actionTable.ContextId;
}
// finds a known the built-in action by string
else if (action != null && action.DescriptionText == "Viewport Configuration")
{
m_builtinVpConfigAction = action;
}
}
}
}
static GlobalDelegates.Delegate5 m_MenuPostLoadDelegate;
static GlobalDelegates.Delegate5 m_MenuPreSaveDelegate;
static GlobalDelegates.Delegate5 m_MenuPostSaveDelegate;
static GlobalDelegates.Delegate5 m_SystemStartupDelegate;
static string menuName = "ADN SampleMenu";
private static void MenuPostLoadHandler(IntPtr objPtr, INotifyInfo infoPtr)
{
var global = GlobalInterface.Instance;
var ip = global.COREInterface13;
IIMenuManager manager = ip.MenuManager;
IIMenu menu = manager.FindMenu(menuName);
if (menu == null)
InstallMenu();
}
private static void MenuPreSaveHandler(IntPtr objPtr, INotifyInfo infoPtr)
{
var global = GlobalInterface.Instance;
var ip = global.COREInterface13;
IIMenuManager manager = ip.MenuManager;
IIMenu menu = manager.FindMenu(menuName);
if (menu != null)
RemoveMenu(menuName);
}
private static void MenuPostSaveHandler(IntPtr objPtr, INotifyInfo infoPtr)
{
var global = GlobalInterface.Instance;
var ip = global.COREInterface13;
IIMenuManager manager = ip.MenuManager;
IIMenu menu = manager.FindMenu(menuName);
if (menu == null)
InstallMenu();
}
private static void MenuSystemStartupHandler(IntPtr objPtr, INotifyInfo infoPtr)
{
var global = GlobalInterface.Instance;
var ip = global.COREInterface13;
IIMenuManager manager = ip.MenuManager;
IIMenu menu = manager.FindMenu(menuName);
if (menu == null)
InstallMenu();
}
/// <summary>
/// This method setups all possible callbacks to handle menus add/remove in various user actions. For example,
/// if the user changes workspaces, the entire menu bar is updated, so this handles adding it in all workspaces as switched.
/// The drawback is that 3ds Max calls some more than once, so you get some seemingly unnecessary add/remove. But it's safer
/// if you always want your menu present.
/// Of course you could also call the add/remove in other conexts and callbacks depending on the 3ds max state where
/// you need your menu to display.
/// </summary>
public static void SetupMenuHandlers()
{
var global = GlobalInterface.Instance;
m_MenuPostLoadDelegate = new GlobalDelegates.Delegate5(MenuPostLoadHandler);
m_MenuPreSaveDelegate = new GlobalDelegates.Delegate5(MenuPreSaveHandler);
m_MenuPostSaveDelegate = new GlobalDelegates.Delegate5(MenuPostSaveHandler);
m_SystemStartupDelegate = new GlobalDelegates.Delegate5(MenuSystemStartupHandler);
global.RegisterNotification(m_MenuPostLoadDelegate, null, SystemNotificationCode.CuiMenusPostLoad);
global.RegisterNotification(m_MenuPreSaveDelegate, null, SystemNotificationCode.CuiMenusPreSave);
global.RegisterNotification(m_MenuPostSaveDelegate, null, SystemNotificationCode.CuiMenusPostSave);
// this will add it at startup and for some scenerios is enough. But a commercial app shuold consider above for workspace switching.
global.RegisterNotification(m_SystemStartupDelegate, null, SystemNotificationCode.SystemStartup);
}
/// <summary>
/// Installs the menu from scratch
/// </summary>
/// <returns>1 when successfully installed, or 0 in error state</returns>
private static uint InstallMenu()
{
try
{
LookupActions();
IGlobal global = GlobalInterface.Instance;
IIActionManager actionManager = global.COREInterface.ActionManager;
IIMenuManager menuManager = global.COREInterface.MenuManager;
// this only needs to be done once
global.COREInterface.MenuManager.RegisterMenuBarContext(0x58527952, menuName);
IIMenu mainMenuBar = menuManager.MainMenuBar;
IIMenu adnSampleMenu = global.IMenu;
adnSampleMenu.Title = menuName;
menuManager.RegisterMenu(adnSampleMenu, 0);
// Launch option
{
IIMenuItem menuItem1 = global.IMenuItem;
menuItem1.ActionItem = m_mouseAction; // uses text from ActionItem.DescriptionText
adnSampleMenu.AddItem(menuItem1, -1);
IIMenuItem menuItem2 = global.IMenuItem;
menuItem2.ActionItem = m_builtinVpConfigAction;
menuItem2.Title = "ADN Menu Sample - " + menuItem2.ActionItem.DescriptionText; // just to show you can override the text, too.
menuItem2.UseCustomTitle = true;
adnSampleMenu.AddItem(menuItem2, -1);
}
// }
IIMenuItem adnMenu = global.IMenuItem;
adnMenu.Title = menuName;
adnMenu.SubMenu = adnSampleMenu;
menuManager.MainMenuBar.AddItem(adnMenu, -1);
global.COREInterface.MenuManager.UpdateMenuBar();
}
catch
{
return 0;
}
return 1;
}
/// <summary>
/// removes the menu
/// </summary>
/// <param name="menuName"></param>
private static void RemoveMenu(string menuName)
{
IGlobal global = GlobalInterface.Instance;
IIActionManager actionManager = global.COREInterface.ActionManager;
IIMenuManager menuManager = global.COREInterface.MenuManager;
IIMenu customMenu = menuManager.FindMenu(menuName);
menuManager.UnRegisterMenu(customMenu);
global.ReleaseIMenu(customMenu);
customMenu = null;
}
}
}