NetRenderAutomation for 2019?
Hi,
I use NetRenderAutomation script for 3DSmax 2015 by Gravey https://forums.cgsociety.org/t/how-to-net-render-with-dependencies/1558453. The script works well, but since the 2018/2019 version, I have a problem.
What has changed since the 2015 version?
Would anyone have a solution?
Can this come from the 64bits version?
Thx :)
struct NetRenderAutomation ( fn CheckGlobal glob string_pattern = ( glob == undefined OR NOT isKindOf glob dotnetobject OR NOT matchpattern ( glob.ToString() ) pattern:string_pattern ), fn CreatePInvokeAssembly forceRecompile:false = ( if forceRecompile OR CheckGlobal ::PInvokeAssembly "*Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" OR CheckGlobal ::User32 "PInvoke.User32" do ( source = "" append source "using System;\n" append source "using System.Runtime.InteropServices;\n" append source "namespace PInvoke\n" append source "{\n" -- open namespace PInvoke append source "public class User32\n" append source "{\n" -- open class append source " [DllImport(\"user32.dll\")]\n" append source " public static extern bool SetDlgItemText(IntPtr hDlg, int nIDDlgItem, string lpString);\n" append source " [DllImport(\"user32.dll\", CharSet = CharSet.Auto)]\n" append source " public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);\n" append source "}\n" -- end class append source "[StructLayout(LayoutKind.Sequential)]\n" append source "public struct LVITEM\n" append source "{\n" -- open class append source " public UInt32 mask;\n" append source " public Int32 iItem;\n" append source " public Int32 iSubItem;\n" append source " public UInt32 state;\n" append source " public UInt32 stateMask;\n" append source " public IntPtr pszText;\n" append source " public Int32 cchTextMax;\n" append source " public Int32 iImage;\n" append source " public Int32 lParam;\n" append source "}\n" -- end class append source "public class Memory\n" append source "{\n" -- open class append source " public static unsafe IntPtr Alloc(int cb)\n" append source " {\n" -- open method Alloc append source " IntPtr data = Marshal.AllocHGlobal(cb);\n" append source " byte* p = (byte*)data.ToPointer();\n" append source " for (int i = 0; i < cb; ++i)\n" append source " {\n" -- open for loop append source " *p = 0; ++p;\n" append source " }\n" -- close for loop append source " return data;\n" append source " }\n" -- close method Alloc append source " public static void Free(IntPtr pointer)" append source " {\n" -- open method Free append source " Marshal.FreeHGlobal(pointer);\n" append source " }\n" -- close method Free append source " public static byte[] GetByteArray(IntPtr pointer, int count)" append source " {\n" -- open method GetByteArray append source " byte[] bytes = new byte[count];\n" append source " Marshal.Copy(pointer, bytes, 0, count);\n" append source " return bytes;\n" append source " }\n" -- close method GetByteArray append source "}\n" -- end class append source "}\n" -- end namespace PInvoke csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider" compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters" compilerParams.ReferencedAssemblies.Add "System.dll" compilerParams.ReferencedAssemblies.Add "mscorlib.dll" compilerParams.CompilerOptions = "/unsafe" compilerParams.GenerateInMemory = on compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source) for i = 1 to compilerResults.Errors.count do ( showall compilerResults.Errors.Item[i-1] ) ::PInvokeAssembly = compilerResults.CompiledAssembly ::User32 = ::PInvokeAssembly.CreateInstance "PInvoke.User32" ) ::PInvokeAssembly ), ------------------------------------------------------------------------------------------------ Memory, -- "PInvoke.Memory" IntPtr = dotnetclass "System.IntPtr", UInt32 = dotnetclass "System.UInt32", Activator = dotnetclass "System.Activator", GCHandle = dotnetclass "System.Runtime.InteropServices.GCHandle", GCHandleType = dotnetclass "System.Runtime.InteropServices.GCHandleType", Encoding = dotnetclass "System.Text.Encoding", StringClass = dotnetclass "System.String", ------------------------------------------------------------------------------------------------ LVM_FIRST = 0x1000, LVM_GETITEMCOUNT = LVM_FIRST + 4, LVM_GETITEMA = LVM_FIRST + 5, LVM_GETITEMW = LVM_FIRST + 75, LVM_GETITEM = LVM_GETITEMW, LVM_SETITEMA = LVM_FIRST + 6, LVM_SETITEMW = LVM_FIRST + 76, LVM_SETITEM = LVM_SETITEMW, ------------------------------------------------------------------------------------------------ LVIF_TEXT = 0x0001, LVIF_STATE = 0x0008, LVIF_MASK = bit.OR LVIF_TEXT LVIF_STATE, ------------------------------------------------------------------------------------------------ LVIS_SELECTED = 0x0002, ------------------------------------------------------------------------------------------------ LISTBOX_BASE = 383, LB_SETSEL = LISTBOX_BASE + 6, LB_GETTEXT = LISTBOX_BASE + 10, LB_GETCOUNT = LISTBOX_BASE + 12, LB_ERR = -1, ------------------------------------------------------------------------------------------------ manager_name = undefined, include_maps = false, suspended = false, specific_servers = #(), dependencies = #(), job_name = "job_name", job_priority = 50, critical = false, ------------------------------------------------------------------------------------------------ fn Alloc num_bytes = ( ptr = Memory.Alloc num_bytes dotnetobject IntPtr ptr ), ------------------------------------------------------------------------------------------------ fn ListView_SendMessage handle _message &item _wparam:0 = ( pinned_item = GCHandle.Alloc item GCHandleType.Pinned item_ptr = dotnetobject IntPtr ( pinned_item.AddrOfPinnedObject() ) h = dotnetobject IntPtr handle message = dotnetobject "System.UInt32" _message wparam = dotnetobject IntPtr _wparam result = 0 try ( result = ::User32.SendMessage h message wparam item_ptr ) catch ( format "-- h: %\n" h format "-- message: %\n" message format "-- wparam: %\n" wparam format "-- item_ptr: %\n" item_ptr format "-- item: %\n" item format "%\n" ( GetCurrentException() ) ) pinned_item.Free() result ), fn ListView_GetNewItem item_index sub_item_index = ( item = ::PInvokeAssembly.CreateInstance "PInvoke.LVITEM" item.mask = LVIF_MASK item.stateMask = LVIS_SELECTED item.iItem = item_index item.iSubItem = sub_item_index item.cchTextMax = 256 item ), -- HWND handle, int item_index, int sub_item_index, out LVITEM &item fn ListView_GetItemText handle &item = ( item.pszText = Alloc item.cchTextMax ListView_SendMessage handle LVM_GETITEM &item ), fn ListView_SetItemSelected handle &item = ( item.mask = LVIF_STATE item.state = LVIS_SELECTED item.stateMask = LVIS_SELECTED ListView_SendMessage handle LVM_SETITEM &item ), fn ListView_GetItemCount handle = ( windows.SendMessage handle LVM_GETITEMCOUNT 0 0 ), ------------------------------------------------------------------------------------------------ fn ListBox_GetCount handle = ( windows.SendMessage handle LB_GETCOUNT 0P 0P ), fn ListBox_GetText handle item_index buffer_ptr = ( try ( h = dotnetobject IntPtr handle wparam = dotnetobject IntPtr item_index ::User32.SendMessage h LB_GETTEXT wparam buffer_ptr ) catch ( format "-- i: % -- %\n" i ( GetCurrentException() ) format "-- handle: %\n" handle format "-- h: %\n" h format "-- wparam: %\n" wparam format "-- buffer_ptr: %\n" buffer_ptr LB_ERR ) ), fn ListBox_GetAllItems handle = ( buffer_size = 256 buffer_ptr = Alloc buffer_size items = #() count = ListBox_GetCount handle for i = 0 to count-1 do ( result = ListBox_GetText handle i buffer_ptr if result != LB_ERR do ( bytes = Memory.GetByteArray buffer_ptr buffer_size item = Encoding.Unicode.GetString bytes append items item ) ) Memory.Free buffer_ptr items ), fn ListBox_SelectItem handle item_index = ( windows.SendMessage handle LB_SETSEL 1 item_index ), ------------------------------------------------------------------------------------------------ mapped fn PrintElement handle numTabs:0 = ( class_name = UIAccessor.GetWindowClassName handle class_name = dotnetobject StringClass ( class_name as string ) window_text = UIAccessor.GetWindowText handle for i = 1 to numTabs do format "\t" format "%\"%\"\n" ( class_name.PadRight 75 ) window_text ), fn PrintChildrenRecursive WindowHandle depth:0 = ( children = windows.getChildrenHWND WindowHandle if children != undefined then ( children = for h in children where h[1] != 0 collect h[1] for handle in children while NOT keyboard.escPressed do ( PrintElement handle numTabs:depth PrintChildrenRecursive handle depth:(depth+1) ) ) OK ), fn GetChildren handle = ( children = windows.getChildrenHWND handle if children != undefined then for h in children where h[1] != 0 collect h[1] else #() ), fn GetElementsByClass handle_arr class_string = ( results = #() for handle in handle_arr do ( className = UIAccessor.GetWindowClassName handle if matchpattern className pattern:class_string do appendIfUnique results handle ) results ), fn PressButtonByHandle handle = ( BM_CLICK = 0xF5 windows.SendMessage handle BM_CLICK 0 0 ), -- state: 0 unchecked, 1 checked, 2 indeterminate fn Checkbox_SetState handle state = ( BM_SETCHECK = 0xF1 windows.SendMessage handle BM_SETCHECK state 0 ), ------------------------------------------------------------------------------------------------ fn FindByName controls window_text_pattern = ( notFound = true ret_handle = 0 for handle in controls while notFound where matchpattern (UIAccessor.GetWindowText handle) pattern:window_text_pattern do ( ret_handle = handle notFound = false ) ret_handle ), fn FindPressButton buttons window_text_pattern press_func:UIAccessor.PressButton = ( handle = FindByName buttons window_text_pattern if handle != 0 then press_func handle else format "failed to find button control with text pattern: %\n" window_text_pattern handle ), fn FindSetCheckboxState buttons window_text_pattern state = ( handle = FindByName buttons window_text_pattern if handle != 0 then Checkbox_SetState handle state else format "failed to find checkbox control with text pattern: %\n" window_text_pattern handle ), fn FindChangeText text_controls window_text_pattern new_text = ( handle = FindByName text_controls window_text_pattern debug:true if handle != 0 then UIAccessor.SetWindowText handle new_text else format "failed to find text control with text pattern: %\n" window_text_pattern handle ), ------------------------------------------------------------------------------------------------ fn DialogAutomation = ( WindowHandle = DialogMonitorOPS.GetWindowHandle() WindowText = UIAccessor.GetWindowText WindowHandle -- format "WindowText: %\n" WindowText if classof WindowText != string then true else ( if matchpattern WindowText pattern:"*Network Job Assignment*" then ( -- format "--- Net Render Dialog : % ---\n" WindowHandle children = GetChildren WindowHandle buttons = GetElementsByClass children "Button" listViews = GetElementsByClass children "SysListView32" edits = GetElementsByClass children "Edit" if isKindOf manager_name string AND manager_name.count != 0 then ( FindSetCheckboxState buttons "*Automatic*" 0 UIAccessor.SetWindowText edits[5] manager_name ) else FindSetCheckboxState buttons "*Automatic*" 1 FindPressButton buttons "&Connect" FindSetCheckboxState buttons "*Notifications*" 0 FindSetCheckboxState buttons "*Split Scan*" 0 FindSetCheckboxState buttons "*Ignore Scene*" 0 FindSetCheckboxState buttons "*Maps*" (if include_maps == true then 1 else 0) FindSetCheckboxState buttons "*Frame Window*" 1 FindSetCheckboxState buttons "*Suspended*" (if suspended == true then 1 else 0) serverView = listViews[1] count = ListView_GetItemCount serverView -- format "server count : %\n" count servers = #() for i = 0 to count-1 do ( item = ListView_GetNewItem i 0 result = ListView_GetItemText serverView &item -- format "result : %\n" result serverName = "" text_ptr = dotnetobject IntPtr item.pszText try ( bytes = Memory.GetByteArray text_ptr item.cchTextMax -- with printAllElements on format "bytes: %\n" bytes serverName = Encoding.Unicode.GetString bytes -- format "serverName: '%'\n" serverName ) catch ( format "i: % -- %\n" i ( GetCurrentException() ) ) Memory.Free text_ptr notFound = true for s in specific_servers while notFound where matchpattern serverName pattern:s do ( ListView_SetItemSelected listviews[1] &item notFound = false ) ) for handle in buttons do ( window_text = UIAccessor.GetWindowText handle if specific_servers.count > 0 AND matchpattern window_text pattern:"Use Sele&cted" then ( -- format "%\n" window_text UIAccessor.PressButton handle ) else if specific_servers.count == 0 AND matchpattern window_text pattern:"&Use All Servers" then ( -- format "%\n" window_text UIAccessor.PressButton handle ) ) textControls = GetElementsByClass children "Edit" UIAccessor.SetWindowText textControls[1] job_name if critical == true then FindSetCheckboxState buttons "Cri&tical" 1 else ( FindSetCheckboxState buttons "Cri&tical" 0 FindChangeText textControls "50" (job_priority as string) ) if dependencies.count != 0 do FindPressButton buttons "&Dependencies" ::SUBMIT_HANDLE = FindPressButton buttons "&Submit" -- FindPressButton buttons "*Cancel*" ) else if matchpattern WindowText pattern:"*Job Dependencies*" then ( children = GetChildren WindowHandle listboxes = GetElementsByClass children "ListBox" items = ListBox_GetAllItems listboxes[1] for i = 1 to items.count do ( for d in dependencies where matchpattern items[i] pattern:d do ListBox_SelectItem listboxes[1] (i-1) ) buttons = GetElementsByClass children "Button" FindPressButton buttons "&Add" FindPressButton buttons "OK" ) else if matchpattern WindowText pattern:"3ds max" then ( children = GetChildren WindowHandle buttons = GetElementsByClass children "Button" FindPressButton buttons "&Yes" ) else if matchpattern WindowText pattern:"*Output Overwrite Alert*" then ( children = GetChildren WindowHandle buttons = GetElementsByClass children "Button" FindPressButton buttons "*Yes*" ) else if matchpattern WindowText pattern:"Render Region" then ( children = GetChildren WindowHandle buttons = GetElementsByClass children "Button" FindPressButton buttons "*OK*" ) ) true ), ------------------------------------------------------------------------------------------------ fn SubmitNetRender = ( RenderSceneDialog.Close() --------------------------------- DialogMonitorOPS.Enabled = false DialogMonitorOPS.unRegisterNotification id:#NET_RENDER_DIALOG_AUTOMATION DialogMonitorOPS.RegisterNotification DialogAutomation id:#NET_RENDER_DIALOG_AUTOMATION DialogMonitorOPS.Enabled = true --------------------------------- oldRendUseNet = rendUseNet rendUseNet = true max quick render --------------------------------- DialogMonitorOPS.Enabled = false DialogMonitorOPS.unRegisterNotification id:#NET_RENDER_DIALOG_AUTOMATION --------------------------------- rendUseNet = oldRendUseNet OK ), on create do ( CreatePInvokeAssembly forceRecompile:false Memory = ::PInvokeAssembly.CreateInstance "PInvoke.Memory" OK ) ) OK -- clearListener() nra = NetRenderAutomation() -- nra.manager_name = "superbeast" -- nra.include_maps = true -- nra.suspended = true -- nra.specific_servers = #( "render-07", "render-09" ) -- nra.dependencies = #( "Existing Job Name A", "Existing_Job_Name_B" ) nra.job_name = "NameObjCurrent" --nra.job_priority = 53 -- nra.critical = true nra.SubmitNetRender() <code>