/// <summary> /// Checks the state of the object. /// If it is outside print are it starts pulsing /// </summary> public void updateSTLState(STL stl) { FormPrinterSettings ps = Main.printerSettings; stl.UpdateBoundingBox(); if (stl.xMin < ps.BedLeft || stl.yMin < ps.BedFront || stl.zMin < -0.001 || stl.xMax > ps.BedLeft + Main.printerSettings.PrintAreaWidth || stl.yMax > ps.BedFront + Main.printerSettings.PrintAreaDepth || stl.zMax > Main.printerSettings.PrintAreaHeight) { stl.outside = true; if (Main.threeDSettings.pulseOutside.Checked && !stl.hasAnimationWithName("pulse")) { stl.addAnimation(new PulseAnimation("pulse", 0.03, 0.03, 0.03, 0.3)); } } else { stl.outside = false; stl.removeAnimationWithName("pulse"); } }
public Main() { executeHostCall = new executeHostCommandDelegate(this.executeHostCommand); PiMakerKey = Custom.BaseKey; // Registry.CurrentUser.CreateSubKey("SOFTWARE\\PiMaker"); PiMakerKey.SetValue("installPath", Application.StartupPath); if (Path.DirectorySeparatorChar != '\\' && IsRunningOnMac()) IsMac = true; /*String[] parms = Environment.GetCommandLineArgs(); string lastcom = ""; foreach (string s in parms) { if (lastcom == "-home") { PiMakerKey.SetValue("installPath",s); lastcom = ""; continue; } if (s == "-macosx") IsMac = true; lastcom = s; }*/ main = this; trans = new Trans(Application.StartupPath + Path.DirectorySeparatorChar + "data" + Path.DirectorySeparatorChar + "translations"); SwitchButton.imageOffset = RegMemory.GetInt("onOffImageOffset", 0); generator = new GCodeGenerator(); globalSettings = new GlobalSettings(); conn = new PrinterConnection(); printerSettings = new FormPrinterSettings(); conn.analyzer.start(); threeDSettings = new ThreeDSettings(); InitializeComponent(); editor = new PiMakerEditor(); editor.Dock = DockStyle.Fill; tabGCode.Controls.Add(editor); updateShowFilament(); RegMemory.RestoreWindowPos("mainWindow", this); if (WindowState == FormWindowState.Maximized) Application.DoEvents(); splitLog.SplitterDistance = RegMemory.GetInt("logSplitterDistance", splitLog.SplitterDistance); splitInfoEdit.SplitterDistance = RegMemory.GetInt("infoEditSplitterDistance", Width - 470); if (IsMono) { if (!IsMac) { foreach (ToolStripItem m in menu.Items) { m.Text = m.Text.Replace("&", null); } } if (IsMac) { /*Application.Events.Quit += delegate (object sender, ApplicationEventArgs e) { Application.Quit (); e.Handled = true; }; ApplicationEvents.Reopen += delegate (object sender, ApplicationEventArgs e) { WindowState = FormWindowState.Normal; e.Handled = true; };*/ MinimumSize = new Size(500, 640); tab.MinimumSize = new Size(500, 500); splitLog.Panel1MinSize = 520; splitLog.Panel2MinSize = 100; splitLog.IsSplitterFixed = true; //splitContainerPrinterGraphic.SplitterDistance -= 52; splitLog.SplitterDistance = splitLog.Height - 100; } } slicerToolStripMenuItem.Visible = false; splitLog.Panel2Collapsed = !RegMemory.GetBool("logShow", true); conn.eventConnectionChange += OnPrinterConnectionChange; conn.eventPrinterAction += OnPrinterAction; conn.eventJobProgress += OnJobProgress; stlComposer1 = new STLComposer(); stlComposer1.Dock = DockStyle.Fill; tabModel.Controls.Add(stlComposer1); printPanel = new PrintPanel(); printPanel.Dock = DockStyle.Fill; tabPrint.Controls.Add(printPanel); printerSettings.formToCon(); logView = new LogView(); logView.Dock = DockStyle.Fill; splitLog.Panel2.Controls.Add(logView); skeinforge = new Skeinforge(); PrinterChanged(printerSettings.currentPrinterKey, true); printerSettings.eventPrinterChanged += PrinterChanged; // GCode print preview threedview = new ThreeDControl(); threedview.Dock = DockStyle.Fill; tabPage3DView.Controls.Add(threedview); printPreview = new ThreeDView(); // printPreview.Dock = DockStyle.Fill; // splitContainerPrinterGraphic.Panel2.Controls.Add(printPreview); printPreview.SetEditor(false); printPreview.autoupdateable = true; printVisual = new GCodeVisual(conn.analyzer); printVisual.liveView = true; printPreview.models.AddLast(printVisual); basicTitle = Text; jobPreview = new ThreeDView(); // jobPreview.Dock = DockStyle.Fill; // splitJob.Panel2.Controls.Add(jobPreview); jobPreview.SetEditor(false); jobPreview.models.AddLast(jobVisual); editor.contentChangedEvent += JobPreview; editor.commands = new Commands(); editor.commands.Read("default", "en"); UpdateHistory(); UpdateConnections(); Main.slic3r = new Slic3r(); slicer = new Slicer(); //toolShowLog_CheckedChanged(null, null); updateShowFilament(); assign3DView(); history = new TemperatureHistory(); tempView = new TemperatureView(); tempView.Dock = DockStyle.Fill; tabPageTemp.Controls.Add(tempView); if (IsMono) showWorkdirectoryToolStripMenuItem.Visible = false; new SoundConfig(); stlComposer1.buttonSlice.Text = Trans.T1("L_SLICE_WITH", slicer.SlicerName); // Customizations if (Custom.GetBool("removeTestgenerator", false)) { internalSlicingParameterToolStripMenuItem.Visible = false; testCaseGeneratorToolStripMenuItem.Visible = false; } string titleAdd = Custom.GetString("titleAddition", ""); if (titleAdd.Length > 0) { int p = basicTitle.IndexOf(' '); basicTitle = basicTitle.Substring(0, p) + titleAdd + basicTitle.Substring(p); Text = basicTitle; } slicerPanel.UpdateSelection(); if (Custom.GetBool("removeUpdates", false)) checkForUpdatesToolStripMenuItem.Visible = false; else RHUpdater.checkForUpdates(true); UpdateToolbarSize(); // Add languages foreach (Translation t in trans.translations.Values) { ToolStripMenuItem item = new ToolStripMenuItem(t.language, null, languageSelected); item.Tag = t; languageToolStripMenuItem.DropDownItems.Add(item); } languageChanged += translate; translate(); toolAction.Text = Trans.T("L_IDLE"); toolConnection.Text = Trans.T("L_DISCONNECTED"); }
/* public void RunSlice(string file,float centerx,float centery) * { * if (procConvert != null) * { * MessageBox.Show("Last slice job still running. Slicing of new job is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); * return; * } * SlicingInfo.Start("Slic3r"); * SlicingInfo.SetAction("Analyzing STL file ..."); * try * { * STL stl = new STL(); * stl.Load(file); * stl.UpdateBoundingBox(); * if (stl.xMin > 0 && stl.yMin > 0 && stl.xMax < Main.printerSettings.PrintAreaWidth && stl.yMax < Main.printerSettings.PrintAreaDepth) * { * // User assigned valid position, so we use this * centerx = stl.xMin + (stl.xMax - stl.xMin) / 2; * centery = stl.yMin + (stl.yMax - stl.yMin) / 2; * } * stl.Clear(); * } * catch (Exception e) * { * Main.conn.log(e.ToString(), false, 2); * SlicingInfo.Stop(); * return; * } * SlicingInfo.SetAction("Slicing STL file ..."); * procConvert = new Process(); * try * { * string basedir = (string)Main.main.PiMakerKey.GetValue("installPath",""); * string exname = "slic3r.exe"; * if (Environment.OSVersion.Platform == PlatformID.Unix) * exname = "bin"+Path.DirectorySeparatorChar+"slic3r"; * if (Main.IsMac) * exname = "MacOS" + Path.DirectorySeparatorChar + "slic3r"; * string exe = basedir + Path.DirectorySeparatorChar + "Slic3r" + Path.DirectorySeparatorChar + exname; * slicefile = file; * string target = StlToGCode(file); * if (File.Exists(target)) * File.Delete(target); * procConvert.EnableRaisingEvents = true; * procConvert.Exited += new EventHandler(ConversionExited); * procConvert.StartInfo.FileName = Main.IsMono ? exe : wrapQuotes(exe); * StringBuilder sb = new StringBuilder(); * sb.Append("--nozzle-diameter "); * sb.Append(textNozzleDiameter.Text); * sb.Append(" "); * sb.Append(" -o "); * sb.Append(wrapQuotes(StlToGCode(file))); * sb.Append(" "); * if (checkRelativeE.Checked) * sb.Append("--use-relative-e-distances "); * if (checkComments.Checked) * sb.Append("--gcode-comments "); * // else * // sb.Append("--gcode-comments 0 "); * sb.Append("-j "); * sb.Append(textNumberOfThreads.Text); * if (checkRandomizeStartingPoints.Checked) * sb.Append(" --randomize-start"); * sb.Append(" --z-offset "); * sb.Append(textZOffset.Text); * sb.Append(" --filament-diameter "); * sb.Append(textDiameter.Text); * sb.Append(" --extrusion-multiplier "); * sb.Append(textPackingDensity.Text); * sb.Append(" --temperature "); * sb.Append(textTemperature.Text); * sb.Append(" --infill-speed "); * sb.Append(textPrintFeedrate.Text); * sb.Append(" --solid-infill-speed "); * sb.Append(textSolidInfillSpeed.Text); * sb.Append(" --travel-speed "); * sb.Append(textTravelFeedrate.Text); * sb.Append(" --bridge-speed "); * sb.Append(textBridgeSpeed.Text); * sb.Append(" --perimeter-speed "); * sb.Append(textPerimeterFeedrate.Text); * sb.Append(" --small-perimeter-speed "); * sb.Append(textSmallPerimeterSpeed.Text); * sb.Append(" --bridge-flow-ratio "); * sb.Append(textBridgeFlowRatio.Text); * sb.Append(" --layer-height "); * sb.Append(textLayerHeight.Text); * sb.Append(" --first-layer-speed "); * sb.Append(textFirstLayerSpeed.Text); * sb.Append(" --first-layer-height "); * sb.Append(textFirstLayerHeight.Text); * sb.Append(" --infill-every-layers "); * sb.Append(textInfillEvery.Text); * sb.Append(" --perimeters "); * sb.Append(textPerimeters.Text); * sb.Append(" --solid-layers "); * sb.Append(textSolidLayers.Text); * sb.Append(" --fill-density "); * sb.Append(textFillDensity.Text); * sb.Append(" --fill-angle "); * sb.Append(textFillAngle.Text); * sb.Append(" --fill-pattern "); * sb.Append(comboFillPattern.SelectedItem); * sb.Append(" --solid-fill-pattern "); * sb.Append(comboSolidFillPattern.SelectedItem); * sb.Append(" --retract-length "); * sb.Append(textRetLength.Text); * sb.Append(" --retract-speed "); * sb.Append(textRetSpeed.Text); * sb.Append(" --retract-restart-extra "); * sb.Append(textRetExtraDistance.Text); * sb.Append(" --retract-before-travel "); * sb.Append(textRetMinTravel.Text); * sb.Append(" --retract-lift "); * sb.Append(textRetLift.Text); * sb.Append(" --skirts "); * sb.Append(textSkirtLoops.Text); * sb.Append(" --skirt-distance "); * sb.Append(textSkirtDistance.Text); * sb.Append(" --skirt-height "); * sb.Append(textSkirtHeight.Text); * sb.Append(" --extrusion-width "); * sb.Append(textExtrusionWidth.Text); * sb.Append(" --brim-width "); * sb.Append(textBrim.Text); * sb.Append(" --support-material-threshold "); * sb.Append(textOverhangTreshold.Text); * sb.Append(" --support-material-pattern "); * sb.Append(comboSupportPattern.SelectedItem); * sb.Append(" --support-material-spacing "); * sb.Append(textPatternSpacing.Text); * sb.Append(" --support-material-angle "); * sb.Append(textPatternAngle.Text); * sb.Append(" --print-center "); * sb.Append(centerx.ToString("0",GCode.format)); * sb.Append(","); * sb.Append(centery.ToString("0", GCode.format)); * if (checkEnableCooling.Checked) * { * sb.Append(" --cooling --bridge-fan-speed "); * sb.Append(textCoolBridgeFanSpeed.Text); * sb.Append(" --disable-fan-first-layers "); * sb.Append(textCoolDisableLayer.Text); * sb.Append(" --fan-below-layer-time "); * sb.Append(textCoolEnableBelow.Text); * sb.Append(" --max-fan-speed "); * sb.Append(textCoolMaxFanSpeed.Text); * sb.Append(" --min-fan-speed "); * sb.Append(textCoolMinFanSpeed.Text); * sb.Append(" --min-print-speed "); * sb.Append(textCoolMinPrintSpeed.Text); * sb.Append(" --slowdown-below-layer-time "); * sb.Append(textCoolSlowDownBelow.Text); * } * if (checkGenerateSupportMaterial.Checked) * { * sb.Append(" --support-material --support-material-tool " + comboSupportMaterialTool.SelectedIndex); * } * sb.Append(" --gcode-flavor "); * switch (comboGCodeFlavor.SelectedIndex) * { * case 0: * default: * sb.Append("reprap"); * break; * case 1: * sb.Append("teacup"); * break; * case 2: * sb.Append("makerbot"); * break; * case 3: * sb.Append("mach3"); * break; * case 4: * sb.Append("no-extrusion"); * break; * } * sb.Append(" --first-layer-temperature "); * sb.Append(textFirstLayerTemperature.Text); * sb.Append(" --bed-temperature "); * sb.Append(textBedTemperature.Text); * sb.Append(" --first-layer-bed-temperature "); * sb.Append(textFirstLayerBedTemperature.Text); * if (checkFanAlwaysEnabled.Checked) * { * sb.Append(" --fan-always-on"); * } * sb.Append(" --start-gcode "); * sb.Append(wrapQuotes(basedir+Path.DirectorySeparatorChar+"empty.txt")); * sb.Append(" --end-gcode "); * sb.Append(wrapQuotes(basedir+Path.DirectorySeparatorChar+"empty.txt")); * sb.Append(" "); * sb.Append(wrapQuotes(file)); * Main.conn.log(sb.ToString(), false, 3); * procConvert.StartInfo.Arguments = sb.ToString(); * procConvert.StartInfo.UseShellExecute = false; * procConvert.StartInfo.RedirectStandardOutput = true; * procConvert.OutputDataReceived += new DataReceivedEventHandler(OutputDataHandler); * procConvert.StartInfo.RedirectStandardError = true; * procConvert.ErrorDataReceived += new DataReceivedEventHandler(OutputDataHandler); * procConvert.Start(); * // Start the asynchronous read of the standard output stream. * procConvert.BeginOutputReadLine(); * procConvert.BeginErrorReadLine(); * //Main.main.tab.SelectedTab = Main.main.tabPrint; * } * catch (Exception e) * { * Main.conn.log(e.ToString(), false, 2); * } * }*/ /* public void RunSliceExternal(string file, float centerx, float centery) * { * if (procConvert != null) * { * MessageBox.Show("Last slice job still running. Slicing of new job is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); * return; * } * SlicingInfo.Start("External Slic3r"); * SlicingInfo.SetAction("Analyzing STL file ..."); * try * { * STL stl = new STL(); * stl.Load(file); * stl.UpdateBoundingBox(); * if (stl.xMin > 0 && stl.yMin > 0 && stl.xMax < Main.printerSettings.PrintAreaWidth && stl.yMax < Main.printerSettings.PrintAreaDepth) * { * // User assigned valid position, so we use this * centerx = stl.xMin + (stl.xMax - stl.xMin) / 2; * centery = stl.yMin + (stl.yMax - stl.yMin) / 2; * } * stl.Clear(); * } * catch (Exception e) * { * Main.conn.log(e.ToString(), false, 2); * SlicingInfo.Stop(); * return; * } * SlicingInfo.SetAction("Slicing STL file ..."); * procConvert = new Process(); * try * { * string basedir = (string)Main.main.PiMakerKey.GetValue("installPath", ""); * string exname = "slic3r.exe"; * if (Environment.OSVersion.Platform == PlatformID.Unix) * exname = "bin" + Path.DirectorySeparatorChar + "slic3r"; * if (Main.IsMac) * exname = "MacOS" + Path.DirectorySeparatorChar + "slic3r"; * string exe = basedir + Path.DirectorySeparatorChar + "Slic3r" + Path.DirectorySeparatorChar + exname; * if (File.Exists(BasicConfiguration.basicConf.ExternalSlic3rPath)) * exe = BasicConfiguration.basicConf.ExternalSlic3rPath; * * slicefile = file; * string target = StlToGCode(file); * if (File.Exists(target)) * File.Delete(target); * procConvert.EnableRaisingEvents = true; * procConvert.Exited += new EventHandler(ConversionExited); * procConvert.StartInfo.FileName = Main.IsMono ? exe : wrapQuotes(exe); * StringBuilder sb = new StringBuilder(); * sb.Append("--load "); * sb.Append(wrapQuotes(BasicConfiguration.basicConf.ExternalSlic3rIniFile)); * sb.Append(" --print-center "); * sb.Append(centerx.ToString("0", GCode.format)); * sb.Append(","); * sb.Append(centery.ToString("0", GCode.format)); * sb.Append(" -o "); * sb.Append(wrapQuotes(StlToGCode(file))); * sb.Append(" "); * sb.Append(wrapQuotes(file)); * procConvert.StartInfo.Arguments = sb.ToString(); * procConvert.StartInfo.UseShellExecute = false; * procConvert.StartInfo.RedirectStandardOutput = true; * procConvert.OutputDataReceived += new DataReceivedEventHandler(OutputDataHandler); * procConvert.StartInfo.RedirectStandardError = true; * procConvert.ErrorDataReceived += new DataReceivedEventHandler(OutputDataHandler); * procConvert.Start(); * // Start the asynchronous read of the standard output stream. * procConvert.BeginOutputReadLine(); * procConvert.BeginErrorReadLine(); * //Main.main.tab.SelectedTab = Main.main.tabPrint; * } * catch (Exception e) * { * Main.conn.log(e.ToString(), false, 2); * } * }*/ public void RunSliceNew(string file, float centerx, float centery) { if (procConvert != null) { MessageBox.Show("Last slice job still running. Slicing of new job is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } FormPrinterSettings ps = Main.printerSettings; SlicingInfo.Start("Slic3r"); SlicingInfo.SetAction("Analyzing STL file ..."); try { STL stl = new STL(); stl.Load(file); stl.UpdateBoundingBox(); if (stl.xMin > ps.BedLeft && stl.yMin > ps.BedFront && stl.xMax < ps.BedLeft + ps.PrintAreaWidth && stl.yMax < ps.BedFront + ps.PrintAreaDepth) { // User assigned valid position, so we use this centerx = stl.xMin + (stl.xMax - stl.xMin) / 2; centery = stl.yMin + (stl.yMax - stl.yMin) / 2; } stl.Clear(); } catch (Exception e) { Main.conn.log(e.ToString(), false, 2); SlicingInfo.Stop(); return; } SlicingInfo.SetAction("Slicing STL file ..."); string dir = Main.globalSettings.Workdir; string config = dir + Path.DirectorySeparatorChar + "slic3r.ini"; string cdir = Main.main.slicerPanel.slic3rDirectory; IniFile ini = new IniFile(); BasicConfiguration b = BasicConfiguration.basicConf; string fPrinter = cdir + Path.DirectorySeparatorChar + "print" + Path.DirectorySeparatorChar + b.Slic3rPrintSettings + ".ini"; ini.read(fPrinter); IniFile ini2 = new IniFile(); ini2.read(cdir + Path.DirectorySeparatorChar + "printer" + Path.DirectorySeparatorChar + b.Slic3rPrinterSettings + ".ini"); IniFile ini3 = new IniFile(); ini3.read(cdir + Path.DirectorySeparatorChar + "filament" + Path.DirectorySeparatorChar + b.Slic3rFilamentSettings + ".ini"); IniFile ini3_2 = new IniFile(); ini3_2.read(cdir + Path.DirectorySeparatorChar + "filament" + Path.DirectorySeparatorChar + b.Slic3rFilament2Settings + ".ini"); IniFile ini3_3 = new IniFile(); ini3_3.read(cdir + Path.DirectorySeparatorChar + "filament" + Path.DirectorySeparatorChar + b.Slic3rFilament3Settings + ".ini"); ini3.merge(ini3_2); ini3.merge(ini3_3); ini.add(ini2); ini.add(ini3); ini.flatten(); ini.write(config); procConvert = new Process(); try { string basedir = (string)Main.main.PiMakerKey.GetValue("installPath", ""); string exname = "slic3r.exe"; if (Environment.OSVersion.Platform == PlatformID.Unix) { exname = "slic3r.pl"; } if (Main.IsMac) { exname = "MacOS" + Path.DirectorySeparatorChar + "slic3r"; } string exe = basedir + Path.DirectorySeparatorChar + "Slic3r" + Path.DirectorySeparatorChar + exname; if (File.Exists(BasicConfiguration.basicConf.Slic3rExecutable)) { exe = BasicConfiguration.basicConf.Slic3rExecutable; } slicefile = file; string target = StlToGCode(file); if (File.Exists(target)) { File.Delete(target); } procConvert.EnableRaisingEvents = true; procConvert.Exited += new EventHandler(ConversionExited); procConvert.StartInfo.FileName = Main.IsMono ? exe : wrapQuotes(exe); StringBuilder sb = new StringBuilder(); sb.Append("--load "); sb.Append(wrapQuotes(config)); sb.Append(" --print-center "); sb.Append(centerx.ToString("0", GCode.format)); sb.Append(","); sb.Append(centery.ToString("0", GCode.format)); sb.Append(" -o "); sb.Append(wrapQuotes(StlToGCode(file))); sb.Append(" "); sb.Append(wrapQuotes(file)); procConvert.StartInfo.Arguments = sb.ToString(); procConvert.StartInfo.UseShellExecute = false; procConvert.StartInfo.RedirectStandardOutput = true; procConvert.OutputDataReceived += new DataReceivedEventHandler(OutputDataHandler); procConvert.StartInfo.RedirectStandardError = true; procConvert.ErrorDataReceived += new DataReceivedEventHandler(OutputDataHandler); procConvert.Start(); // Start the asynchronous read of the standard output stream. procConvert.BeginOutputReadLine(); procConvert.BeginErrorReadLine(); //Main.main.tab.SelectedTab = Main.main.tabPrint; } catch (Exception e) { Main.conn.log(e.ToString(), false, 2); } }
public void Autoposition() { if (autosizeFailed) { return; } RectPacker packer = new RectPacker(1, 1); int border = 3; FormPrinterSettings ps = Main.printerSettings; float maxW = ps.PrintAreaWidth; float maxH = ps.PrintAreaDepth; float xOff = ps.BedLeft, yOff = ps.BedFront; if (ps.HasDumpArea) { if (ps.DumpAreaFront <= 0) { yOff = ps.BedFront + ps.DumpAreaDepth - ps.DumpAreaFront; maxH -= yOff; } else if (ps.DumpAreaDepth + ps.DumpAreaFront >= maxH) { yOff = ps.BedFront + -(maxH - ps.DumpAreaFront); maxH += yOff; } else if (ps.DumpAreaLeft <= 0) { xOff = ps.BedLeft + ps.DumpAreaWidth - ps.DumpAreaLeft; maxW -= xOff; } else if (ps.DumpAreaWidth + ps.DumpAreaLeft >= maxW) { xOff = ps.BedLeft + maxW - ps.DumpAreaLeft; maxW += xOff; } } foreach (STL stl in listSTLObjects.Items) { int w = 2 * border + (int)Math.Ceiling(stl.xMax - stl.xMin); int h = 2 * border + (int)Math.Ceiling(stl.yMax - stl.yMin); if (!packer.addAtEmptySpotAutoGrow(new PackerRect(0, 0, w, h, stl), (int)maxW, (int)maxH)) { autosizeFailed = true; } } if (autosizeFailed) { MessageBox.Show("Too many objects on printer bed for automatic packing.\r\nPacking disabled until elements are removed.", "Printer bed full", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } float xAdd = (maxW - packer.w) / 2.0f; float yAdd = (maxH - packer.h) / 2.0f; foreach (PackerRect rect in packer.vRects) { STL s = (STL)rect.obj; float xPos = xOff + xAdd + rect.x + border; float yPos = yOff + yAdd + rect.y + border; s.Position.x += xPos - s.xMin; s.Position.y += yPos - s.yMin; s.UpdateBoundingBox(); } Main.main.threedview.UpdateChanges(); }