Hey guys,
There was a feature I always wanted in 3dsmax but never actually found anything acceptable as a substitute for and that is an actions history window. I really like to see what actions I am doing
to prevent accidentally moving and doing collapses and welds as I try to work fast.
I know you can open the maxscript listener and see actions there but I'd much rather having
something like the right-click undo window permanently visible that I can casually glance at.
The question is whether its possible to have it either with some sort of hack(right now I have an autohotkey script that opens that window for me) or by tapping into the sdk or even via maxscript.
I'd love any input on this as its a feature I'd like to use on a regular basis.
Replies
Hey look at this
http://www.scriptspot.com/3ds-max/scripts/multipurpose-selection-bar
( I searched scriptspot for "undo history" )
Thanks for posting that script, it seems to do what I want however I think its bugged since the undo doesn't show either in max 2015 or 2017.
I think I'll try to tap into the events that get called when there's an undo and read the label of that, I could use the script you posted as reference even if it doesn't seem to work per se.
There must be some array that I can access that will have the undo labels.
Also when you say open the window and parse, you mean pixel read the text via something like autohotkey?
No need for capturing pixels, once you have the window handle, get the child Listbox handle and enumerate its items.
I am gonna try to take this as a base and with my limited Maxscript knowledge make it so when I press a key or after an event fires it will update the list in the rollout.
I will update once I have something working.
Its bare bones but it works. When I hit a key I have Autohotkey set up to clear the listener window and hit the Undo Script button in the UI to update the list.
It makes it looks like this:
Please let me know if you have an idea on how I can change this script to have an update button instead:
macroScript Undoer category:"Undoer" buttontext:"UndoerGO" toolTip:"UndoerGOGO" --icon:#() ( ( --FUNCTIONS local items = #() fn showItems = lbItems = items --listBox lbItems items:items fn sendRightClick hWnd = ( local WM_RBUTTONDOWN = 0x0204 windows.postMessage hWnd WM_RBUTTONDOWN 0 0 windows.postMessage hWnd (WM_RBUTTONDOWN + 1) 0 0 ) fn getListBoxLength hWnd = ( local LB_GETCOUNT = 0x18B windows.sendMessage hWnd LB_GETCOUNT 0 0 ) fn getListBoxItemText hWnd i = ( local LB_GETTEXT = 0x189 local LB_GETTEXTLEN = 0x18A local marshal = dotNetClass "System.Runtime.InteropServices.Marshal" local len = windows.sendMessage hWnd LB_GETTEXTLEN i 0 local lParam = marshal.AllocHGlobal (2 * len + 2) asDotNetObject:on windows.sendMessage hWnd LB_GETTEXT i (lParam.ToInt64()) local str = (marshal.PtrToStringAuto lParam asDotNetObject:on).ToString() marshal.FreeHGlobal lParam return str ) fn collectUndoItems = ( local hWnd = DialogMonitorOPS.getWindowHandle() if UIAccessor.getWindowText hWnd == "" and UIAccessor.getWindowClassName hWnd == "Dialog" then ( local listBoxHWnd = for ctrl in (windows.getChildrenHWnd hWnd) where ctrl[4] == "ListBox" do exit with ctrl[1] local itemCount = getListBoxLength listBoxHWnd items = for i = 0 to itemCount - 1 collect getListBoxItemText listBoxHWnd i UIAccessor.closeDialog hWnd showItems() ii=0 for v in items do ( if ii>6 do exit ii=ii+1 if v == "Move" or v == "Rotate" or v == "Scale" do append v "<>" print v ) DialogMonitorOPS.enabled = off DialogMonitorOPS.unRegisterNotification id:#getUndoStack true ) else false ) fn CallbackFn1 ev nd = ( /* ii=0 for v in items do ( if ii>6 do exit ii=ii+1 --if v == "Move" do print v ) */ ) local maxChildren = windows.getChildrenHWnd #max local undoBtnHWnd = for hWndData in maxChildren where UIAccessor.getWindowResourceID hWndData[1] == 50034 do exit with hWndData[1] if isKindOf undoBtnHWnd Number then ( DialogMonitorOPS.unRegisterNotification id:#getUndoStack DialogMonitorOPS.registerNotification collectUndoItems id:#getUndoStack DialogMonitorOPS.enabled = on callbackItem = NodeEventCallback mouseUp:true delay:1000 subobjectSelectionChanged:CallbackFn1 sendRightClick undoBtnHWnd ) else messageBox "Couldn't find the undo button." ) )