-- Find the Mach4 Directory function GetRecentMachDir() -- https://docs.wxwidgets.org/3.0/classwx_file_config.html local appdata = GetAppDataRoaming() local mm_ini = string.format("%s/MachMotion.ini",appdata) local recent_ini = wx.wxFileConfig('mm_script','MachMotion',"",mm_ini,wx.wxCONFIG_USE_GLOBAL_FILE + wx.wxCONFIG_USE_NO_ESCAPE_CHARACTERS) local key = 'Recent/MachDir' local exists,value = recent_ini:Read(key,"_NOT_FOUND_") if not exists or value == '_NOT_FOUND_' then if not exists then wx.wxLogWarning(string.format("Cannot find key '%s' in %s",key,mm_ini)) else wx.wxLogWarning(string.format("No value for key '%s' in %s",key,mm_ini)) end error("Cannot find recent Mach4 directory") end return value end function GetAppDataRoaming() local is_ok,appdata = pcall(GetAppDataRoaming_Method1) if is_ok then return appdata end local err = appdata wx.wxLogWarning(string.format("Error returned from GetAppDataRoaming_Method1(): %s",err)) is_ok,appdata = pcall(GetAppDataRoaming_Method2) if is_ok then return appdata end err = appdata wx.wxLogWarning(string.format("Error returned from GetAppDataRoaming_Method2(): %s",err)) return 'C:\\Users\\MachMotion\\AppData\\Roaming' -- a good guess, but only a guess end function GetAppDataRoaming_Method1() -- https://docs.wxwidgets.org/3.0/classwx_standard_paths.html -- https://docs.microsoft.com/en-us/windows/win32/shell/csidl -- This is the (morally) superior method. It attempts to do Windows-y stuff to get a special Windows thing. --local FOLDERID_RoamingAppData = '{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}' local CSIDL_APPDATA = 26 local appdata = wx.wxStandardPaths.MSWGetShellDir(CSIDL_APPDATA) return appdata end function GetAppDataRoaming_Method2() -- For use if Method1 doesn't work or isn't available. -- This is correct for Windows 10. IDK about Windows 7. return os.getenv('APPDATA') end -- Build the string with the path to the MachUtil program that unloads and loads the file into mach. machdir = GetRecentMachDir() machUtil = string.format("%s\\tools\\MachUtil\\MachUtil.exe", machdir) function OnAbout(event) ctrl = event:GetTextCtrl() ctrl:AppendText("Mach4 WaterJet post processor - 2 Axis Only\n") ctrl:AppendText("\n") ctrl:AppendText("Generic WaterJet Post\n") ctrl:AppendText("\n") ctrl:AppendText("Modal G-codes and coordinates\n") ctrl:AppendText("Comments enclosed with ( and )\n") ctrl:AppendText("M3 and M5 turn the jet on/off\n") ctrl:AppendText("ABS IJ\n") end -- This breaks the arc's up in 90 degree segments post.SetOptions(post.ARC_SEGMENTS) function OnInit() post.SetCommentChars ("()", "[]") --make sure ( and ) characters do not appear in system text post.Text (" (Filename: ", fileName, ")\n") post.Text (" (Post processor: ", postName, ")\n") post.Text (" (Date: ", date, ")\n") if(scale == metric) then post.Text (" G21 (Units: Metric)\n") --metric mode else post.Text (" G20 (Units: Inches)\n") --inch mode end post.Text (" G90 G90.1 G40\n") dist = 9999999 refdistance = 400 switchoffset = 0 minArcSize = 0.01 --arcs smaller than this are converted to moves end function OnFileOpen() os.execute(machUtil .. " --close-gcode") end function OnFileClosed() os.execute(machUtil .. " --open-gcode \"" .. filePath .. fileName .. "\"") end function OnNewLine() post.Text ("N") post.Number (lineNumber, "0000") lineNumber = lineNumber + 10 end function OnFinish() post.Text (" M30 (Program Rewind)\n") end function OnRapid() if(math.hypot(endX-currentX , endY-currentY) < 0.001 and endZ < currentZ) then return end dist = dist + math.hypot(endX-currentX , endY-currentY) post.Text (" G00") post.NonModalNumber (" X", endX * scale, "0.0000") post.NonModalNumber (" Y", endY * scale, "0.0000") -- post.ModalNumber (" Z", endZ * scale, "0.0000") post.Eol() end function OnMove() dist = dist + math.hypot(endX-currentX , endY-currentY) post.Text (" G01") post.NonModalNumber (" X", endX * scale, "0.0000") post.NonModalNumber (" Y", endY * scale, "0.0000") -- post.ModalNumber (" Z", endZ * scale, "0.0000") post.ModalNumber (" F", feedRate * scale, "0.###") post.Eol() end --function OnArc() -- post.ArcAsMoves(0.01) --end function OnArc() dist = dist + math.hypot(endX-currentX , endY-currentY) if(arcAngle <0) then post.Text(" G03") else post.Text(" G02") end post.NonModalNumber (" X", endX * scale, "0.0000") post.NonModalNumber (" Y", endY * scale, "0.0000") -- post.ModalNumber (" Z", endZ * scale, "0.0000") post.Text (" I") post.Number ((arcCentreX) * scale, "0.0000") post.Text (" J") post.Number ((arcCentreY) * scale, "0.0000") post.ModalNumber (" F", feedRate * scale, "0.0###") post.Eol() end function OnPenDown() post.Eol() post.Text (" G00") -- post.NonModalNumber (" Z", pierceHeight * scale, "0.0000") post.Text (" (Pierce Height)") post.Eol() post.Text (" M3 (Jets Down, Jets On, Abrasive On, Pierce Delay)") post.Eol() post.Text (" G00") -- post.NonModalNumber (" Z", cutHeight * scale, "0.0000") post.Text (" (Cut Height)") post.Eol() end function OnPenUp() post.Eol() post.Text (" M5 (Jets Up, Jets Off, Abrasive Off)") post.Eol() post.Text (" G00") -- post.NonModalNumber (" Z", safeZ * scale, "0.0000") post.Text (" (Rapid Height)") post.Eol() end function OnNewOperation() post.Text (" (Operation: ", operationName, ")\n") end function OnComment() post.Text(" (",commentText,")\n") end function OnToolChange() post.Text (" M06 T") post.Number (tool, "0") post.ModalNumber(" F",feedRate * scale,"0.0###") post.Text (" (", toolName, ")\n") if (feedRate <= 0) then post.Warning("WARNING: Feed rate is zero") end end function OnNewPart() post.Text(" (Part: ",partName,")\n"); end function OnDrill() OnRapid() OnPenDown() endZ = drillZ OnMove() OnPenUp() endZ = safeZ OnRapid() end