public ExportPrintItemPage(IEnumerable <ILibraryItem> libraryItems, bool centerOnBed, PrinterConfig printer) { this.WindowTitle = "Export File".Localize(); this.HeaderText = "Export selection to".Localize() + ":"; this.Name = "Export Item Window"; var commonMargin = new BorderDouble(4, 2); bool isFirstItem = true; // Must be constructed before plugins are initialized var exportButton = theme.CreateDialogButton("Export".Localize()); validationPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit }; // GCode export exportPluginButtons = new Dictionary <RadioButton, IExportPlugin>(); foreach (IExportPlugin plugin in PluginFinder.CreateInstancesOf <IExportPlugin>().OrderBy(p => p.ButtonText)) { plugin.Initialize(printer); // Skip plugins which are invalid for the current printer if (!plugin.Enabled) { if (!string.IsNullOrEmpty(plugin.DisabledReason)) { // add a message to let us know why not enabled var disabledPluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button", Enabled = false }; contentRow.AddChild(disabledPluginButton); contentRow.AddChild(new TextWidget("Disabled: {0}".Localize().FormatWith(plugin.DisabledReason), textColor: theme.PrimaryAccentColor) { Margin = new BorderDouble(left: 80), HAnchor = HAnchor.Left }); } continue; } // Create export button for each plugin var pluginButton = new RadioButton(new RadioImageWidget(plugin.ButtonText, theme.TextColor, plugin.Icon)) { HAnchor = HAnchor.Left, Margin = commonMargin, Cursor = Cursors.Hand, Name = plugin.ButtonText + " Button" }; contentRow.AddChild(pluginButton); if (plugin is GCodeExport) { var gcodeExportButton = pluginButton; gcodeExportButton.CheckedStateChanged += (s, e) => { validationPanel.CloseAllChildren(); if (gcodeExportButton.Checked) { var errors = printer.ValidateSettings(validatePrintBed: false); exportButton.Enabled = !errors.Any(item => item.ErrorLevel == ValidationErrorLevel.Error); validationPanel.AddChild( new ValidationErrorsPanel( errors, AppContext.Theme) { HAnchor = HAnchor.Stretch }); } else { exportButton.Enabled = true; } }; } if (isFirstItem) { pluginButton.Checked = true; isFirstItem = false; } if (plugin is IExportWithOptions pluginWithOptions) { var optionPanel = pluginWithOptions.GetOptionsPanel(); if (optionPanel != null) { optionPanel.HAnchor = HAnchor.Stretch; optionPanel.VAnchor = VAnchor.Fit; contentRow.AddChild(optionPanel); } } exportPluginButtons.Add(pluginButton, plugin); } ContentRow.AddChild(new VerticalSpacer()); contentRow.AddChild(validationPanel); // TODO: make this work on the mac and then delete this if if (AggContext.OperatingSystem == OSType.Windows || AggContext.OperatingSystem == OSType.X11) { showInFolderAfterSave = new CheckBox("Show file in folder after save".Localize(), theme.TextColor, 10) { HAnchor = HAnchor.Left, Cursor = Cursors.Hand }; contentRow.AddChild(showInFolderAfterSave); } exportButton.Name = "Export Button"; exportButton.Click += (s, e) => { IExportPlugin activePlugin = null; // Loop over all plugin buttons, break on the first checked item found foreach (var button in this.exportPluginButtons.Keys) { if (button.Checked) { activePlugin = exportPluginButtons[button]; break; } } // Early exit if no plugin radio button is selected if (activePlugin == null) { return; } DoExport(libraryItems, printer, activePlugin, centerOnBed, showInFolderAfterSave?.Checked == true); this.Parent.CloseOnIdle(); }; this.AddPageAction(exportButton); }
public EditLevelingSettingsPage(PrinterConfig printer, ThemeConfig theme) { this.printer = printer; this.WindowTitle = "Leveling Settings".Localize(); this.HeaderText = "Sampled Positions".Localize(); var scrollableWidget = new ScrollableWidget() { AutoScroll = true, HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Stretch, }; scrollableWidget.ScrollArea.HAnchor = HAnchor.Stretch; contentRow.AddChild(scrollableWidget); // No right padding removes unexpected spacing to the right of scrollbar contentRow.Padding = contentRow.Padding.Clone(right: 0); var column = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch, Padding = new BorderDouble(right: theme.DefaultContainerPadding + 4) }; scrollableWidget.AddChild(column); var positions = new List <Vector3>(); PrintLevelingData levelingData = printer.Settings.Helpers.PrintLevelingData; for (int i = 0; i < levelingData.SampledPositions.Count; i++) { positions.Add(levelingData.SampledPositions[i]); } int tab_index = 0; for (int row = 0; row < positions.Count; row++) { var leftRightEdit = new FlowLayoutWidget { Padding = new BorderDouble(3), HAnchor = HAnchor.Stretch }; var positionLabel = new TextWidget("{0} {1,-5}".FormatWith("Position".Localize(), row + 1), textColor: theme.TextColor); positionLabel.VAnchor = VAnchor.Center; leftRightEdit.AddChild(positionLabel); for (int axis = 0; axis < 3; axis++) { leftRightEdit.AddChild(new HorizontalSpacer()); string axisName = "x"; if (axis == 1) { axisName = "y"; } else if (axis == 2) { axisName = "z"; } leftRightEdit.AddChild( new TextWidget($" {axisName}: ", textColor: theme.TextColor) { VAnchor = VAnchor.Center }); int linkCompatibleRow = row; int linkCompatibleAxis = axis; MHNumberEdit valueEdit = new MHNumberEdit(positions[linkCompatibleRow][linkCompatibleAxis], theme, allowNegatives: true, allowDecimals: true, pixelWidth: 60 * GuiWidget.DeviceScale, tabIndex: tab_index++) { Name = $"{axisName} Position {row}" }; valueEdit.ActuallNumberEdit.InternalTextEditWidget.EditComplete += (sender, e) => { Vector3 position = positions[linkCompatibleRow]; position[linkCompatibleAxis] = valueEdit.ActuallNumberEdit.Value; positions[linkCompatibleRow] = position; }; valueEdit.Margin = new BorderDouble(3); leftRightEdit.AddChild(valueEdit); } column.AddChild(leftRightEdit); } var savePresetsButton = theme.CreateDialogButton("Save".Localize()); savePresetsButton.Name = "Save Leveling Button"; savePresetsButton.Click += (s, e) => { PrintLevelingData newLevelingData = printer.Settings.Helpers.PrintLevelingData; for (int i = 0; i < newLevelingData.SampledPositions.Count; i++) { newLevelingData.SampledPositions[i] = positions[i]; } printer.Settings.Helpers.PrintLevelingData = newLevelingData; this.DialogWindow.Close(); }; this.AddPageAction(savePresetsButton); var exportButton = theme.CreateDialogButton("Export".Localize()); exportButton.Click += (s, e) => { UiThread.RunOnIdle(this.ExportSettings, .1); }; this.AddPageAction(exportButton); }
public static void DoExport(IEnumerable <ILibraryItem> libraryItems, PrinterConfig printer, IExportPlugin exportPlugin, bool centerOnBed = false, bool showFile = false) { string targetExtension = exportPlugin.FileExtension; if (exportPlugin is FolderExport) { UiThread.RunOnIdle(() => { AggContext.FileDialogs.SelectFolderDialog( new SelectFolderDialogParams("Select Location To Export Files") { ActionButtonLabel = "Export".Localize(), Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize() }, (openParams) => { ApplicationController.Instance.Tasks.Execute( "Saving".Localize() + "...", printer, async(reporter, cancellationToken) => { string path = openParams.FolderPath; if (!string.IsNullOrEmpty(path)) { await exportPlugin.Generate(libraryItems, path, reporter, cancellationToken); } }); }); }); return; } UiThread.RunOnIdle(() => { string title = ApplicationController.Instance.ProductName + " - " + "Export File".Localize(); string workspaceName = "Workspace " + DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss"); AggContext.FileDialogs.SaveFileDialog( new SaveFileDialogParams(exportPlugin.ExtensionFilter) { Title = title, ActionButtonLabel = "Export".Localize(), FileName = Path.GetFileNameWithoutExtension(libraryItems.FirstOrDefault()?.Name ?? workspaceName) }, (saveParams) => { string savePath = saveParams.FileName; if (!string.IsNullOrEmpty(savePath)) { ApplicationController.Instance.Tasks.Execute( "Exporting".Localize() + "...", printer, async(reporter, cancellationToken) => { string extension = Path.GetExtension(savePath); if (!extension.Equals(targetExtension, StringComparison.OrdinalIgnoreCase)) { savePath += targetExtension; } List <ValidationError> exportErrors = null; if (exportPlugin != null) { if (exportPlugin is GCodeExport gCodeExport) { gCodeExport.CenterOnBed = centerOnBed; } exportErrors = await exportPlugin.Generate(libraryItems, savePath, reporter, cancellationToken); } if (exportErrors == null || exportErrors.Count == 0) { { if (AggContext.OperatingSystem == OSType.Windows || AggContext.OperatingSystem == OSType.X11) { if (showFile) { AggContext.FileDialogs.ShowFileInFolder(savePath); } } } } else { bool showGenerateErrors = !(exportPlugin is GCodeExport); // Only show errors in Generate if not GCodeExport - GCodeExport shows validation errors before Generate call if (showGenerateErrors) { ApplicationController.Instance.ShowValidationErrors("Export Error".Localize(), exportErrors); } } }); } }); }); }
public MovementSpeedsPage(PrinterConfig printer) { this.AlwaysOnTopOfMain = true; this.WindowTitle = "Movement Speeds".Localize(); this.HeaderText = "Movement Speeds Presets".Localize(); this.WindowSize = new Vector2(500 * GuiWidget.DeviceScale, 320 * GuiWidget.DeviceScale); var rightLabel = new TextWidget("mm/s".Localize(), textColor: theme.TextColor, pointSize: theme.FontSize10) { VAnchor = VAnchor.Center, Margin = new BorderDouble(right: 20) }; var headerBar = new Toolbar(theme, rightLabel) { Height = theme.ButtonHeight, Padding = theme.ToolbarPadding, HAnchor = HAnchor.Stretch }; headerBar.AddChild(new TextWidget(this.WindowTitle, textColor: theme.TextColor, pointSize: theme.FontSize10)); contentRow.AddChild(headerBar); // put in the movement edit controls string[] settingsArray = printer.Settings.Helpers.GetMovementSpeedsString().Split(','); int preset_count = 1; int tab_index = 0; for (int i = 0; i < settingsArray.Count() - 1; i += 2) { var row = new FlowLayoutWidget { Padding = 3, HAnchor = HAnchor.Stretch }; TextWidget axisLabel; if (settingsArray[i].StartsWith("e")) { axisLabel = new TextWidget(string.Format("{0}(s)", "Extruder".Localize()), textColor: theme.TextColor); } else { axisLabel = new TextWidget(string.Format("{0} {1}", "Axis".Localize(), settingsArray[i].ToUpper()), textColor: theme.TextColor); } axisLabel.VAnchor = VAnchor.Center; row.AddChild(axisLabel); row.AddChild(new HorizontalSpacer()); axisLabels.Add(settingsArray[i]); if (double.TryParse(settingsArray[i + 1], out double movementSpeed)) { movementSpeed = movementSpeed / 60.0; // Convert from mm/min to mm/s } var valueEdit = new MHNumberEdit(movementSpeed, theme, minValue: 0, pixelWidth: 60 * GuiWidget.DeviceScale, tabIndex: tab_index++, allowDecimals: true) { Margin = 3 }; row.AddChild(valueEdit); valueEditors.Add(valueEdit); contentRow.AddChild(row); preset_count += 1; } var savePresetsButton = theme.CreateDialogButton("Save".Localize()); savePresetsButton.Click += (s, e) => { bool first = true; var settingString = new StringBuilder(); for (int i = 0; i < valueEditors.Count(); i++) { if (!first) { settingString.Append(","); } first = false; settingString.Append(axisLabels[i]); settingString.Append(","); double movementSpeed = 0; double.TryParse(valueEditors[i].Text, out movementSpeed); movementSpeed = movementSpeed * 60; // Convert to mm/min settingString.Append(movementSpeed.ToString()); } string speedString = settingString.ToString(); if (!string.IsNullOrEmpty(speedString)) { printer.Settings.SetValue(SettingsKey.manual_movement_speeds, speedString); printer.Bed.GCodeRenderer?.Clear3DGCode(); } this.DialogWindow.CloseOnIdle(); }; this.AddPageAction(savePresetsButton); }
public JogControls(PrinterConfig printer, XYZColors colors, ThemeConfig theme) { this.theme = theme; this.printer = printer; double distanceBetweenControls = 12; double buttonSeparationDistance = 10; var allControlsTopToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch }; var allControlsLeftToRight = new FlowLayoutWidget(); using (allControlsLeftToRight.LayoutLock()) { var xYZWithDistance = new FlowLayoutWidget(FlowDirection.TopToBottom); { var xYZControls = new FlowLayoutWidget(); xYZControls.AddChild(this.CreateXYGridControl(colors, distanceBetweenControls, buttonSeparationDistance)); FlowLayoutWidget zButtons = JogControls.CreateZButtons(printer, buttonSeparationDistance, out zPlusControl, out zMinusControl, colors, theme); zButtons.VAnchor = VAnchor.Bottom; xYZControls.AddChild(zButtons); xYZWithDistance.AddChild(xYZControls); // add in some movement radio buttons var setMoveDistanceControl = new FlowLayoutWidget { HAnchor = HAnchor.Left | HAnchor.Fit, VAnchor = VAnchor.Fit }; { var moveRadioButtons = new FlowLayoutWidget(); var radioList = new List <GuiWidget>(); movePointZeroTwoMmButton = theme.CreateMicroRadioButton("0.02", radioList); movePointZeroTwoMmButton.CheckedStateChanged += (s, e) => { if (movePointZeroTwoMmButton.Checked) { SetXYZMoveAmount(.02); } }; moveRadioButtons.AddChild(movePointZeroTwoMmButton); var pointOneButton = theme.CreateMicroRadioButton("0.1", radioList); pointOneButton.CheckedStateChanged += (s, e) => { if (pointOneButton.Checked) { SetXYZMoveAmount(.1); } }; moveRadioButtons.AddChild(pointOneButton); moveOneMmButton = theme.CreateMicroRadioButton("1", radioList); moveOneMmButton.CheckedStateChanged += (s, e) => { if (moveOneMmButton.Checked) { SetXYZMoveAmount(1); } }; moveRadioButtons.AddChild(moveOneMmButton); tenButton = theme.CreateMicroRadioButton("10", radioList); tenButton.CheckedStateChanged += (s, e) => { if (tenButton.Checked) { SetXYZMoveAmount(10); } }; moveRadioButtons.AddChild(tenButton); oneHundredButton = theme.CreateMicroRadioButton("100", radioList); oneHundredButton.CheckedStateChanged += (s, e) => { if (oneHundredButton.Checked) { SetXYZMoveAmount(100); } }; moveRadioButtons.AddChild(oneHundredButton); tenButton.Checked = true; SetXYZMoveAmount(10); moveRadioButtons.Margin = new BorderDouble(0, 3); setMoveDistanceControl.AddChild(moveRadioButtons); moveRadioButtons.AddChild(new TextWidget("mm", textColor: theme.TextColor, pointSize: 8) { Margin = new BorderDouble(left: 10), VAnchor = VAnchor.Center }); } xYZWithDistance.AddChild(setMoveDistanceControl); } allControlsLeftToRight.AddChild(xYZWithDistance); #if !__ANDROID__ allControlsLeftToRight.AddChild(GetHotkeyControlContainer()); #endif // Bar between Z And E allControlsLeftToRight.AddChild(new GuiWidget(1, 1) { VAnchor = VAnchor.Stretch, BackgroundColor = colors.ZColor, Margin = new BorderDouble(distanceBetweenControls, 5) }); // EButtons disableableEButtons = CreateEButtons(buttonSeparationDistance, colors); disableableEButtons.Name = "disableableEButtons"; disableableEButtons.HAnchor = HAnchor.Fit; disableableEButtons.VAnchor = VAnchor.Fit | VAnchor.Top; allControlsLeftToRight.AddChild(disableableEButtons); allControlsTopToBottom.AddChild(allControlsLeftToRight); } allControlsLeftToRight.PerformLayout(); using (this.LayoutLock()) { this.AddChild(allControlsTopToBottom); this.HAnchor = HAnchor.Fit; this.VAnchor = VAnchor.Fit; Margin = new BorderDouble(3); } this.PerformLayout(); // Register listeners printer.Settings.SettingChanged += Printer_SettingChanged; }
public static (Mesh bed, Mesh volume) CreatePrintBedAndVolume(PrinterConfig printer) { Mesh printerBed; Mesh buildVolume = null; var displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1)); // Temporarily assign a placeholder image as the mesh texture. This will be replaced with a themed image by the view var placeHolderImage = new ImageBuffer(5, 5); var graphics = placeHolderImage.NewGraphics2D(); graphics.Clear(Color.Gray.WithAlpha(40)); switch (printer.Bed.BedShape) { case BedShape.Rectangular: if (displayVolumeToBuild.Z > 0) { buildVolume = PlatonicSolids.CreateCube(displayVolumeToBuild); for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] + new Vector3Float(0, 0, displayVolumeToBuild.Z / 2); } var bspTree = FaceBspTree.Create(buildVolume); buildVolume.FaceBspTree = bspTree; } printerBed = PlatonicSolids.CreateCube(displayVolumeToBuild.X, displayVolumeToBuild.Y, 1.8); printerBed.PlaceTextureOnFaces(0, placeHolderImage); break; case BedShape.Circular: { if (displayVolumeToBuild.Z > 0) { buildVolume = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), displayVolumeToBuild.Z); } printerBed = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), 1.8); printerBed.PlaceTextureOnFaces(0, placeHolderImage); } break; default: throw new NotImplementedException(); } var zTop = printerBed.GetAxisAlignedBoundingBox().MaxXYZ.Z; for (int i = 0; i < printerBed.Vertices.Count; i++) { printerBed.Vertices[i] = printerBed.Vertices[i] - new Vector3Float(-printer.Bed.BedCenter, zTop + .02); } if (buildVolume != null) { for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] - new Vector3Float(-printer.Bed.BedCenter, zTop + .02); } } return(printerBed, buildVolume); }
private static ImageBuffer CreateRectangularBedGridImage(PrinterConfig printer) { var displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1)); double sizeForMarking = Math.Max(displayVolumeToBuild.X, displayVolumeToBuild.Y); double divisor = 10; int skip = 1; if (sizeForMarking > 1000) { divisor = 100; skip = 10; } else if (sizeForMarking > 300) { divisor = 50; skip = 5; } var theme = AppContext.Theme; var bedMarkingsColor = theme.PrinterBedTextColor; var bedplateImage = new ImageBuffer(1024, 1024); Graphics2D graphics2D = bedplateImage.NewGraphics2D(); graphics2D.Clear(theme.BedColor); { double lineDist = bedplateImage.Width / (displayVolumeToBuild.X / divisor); double xPositionCm = (-(printer.Bed.ViewerVolume.X / 2.0) + printer.Bed.BedCenter.X) / divisor; int xPositionCmInt = (int)Math.Round(xPositionCm); double fraction = xPositionCm - xPositionCmInt; int pointSize = 20; graphics2D.DrawString((xPositionCmInt * skip).ToString(), 4, 4, pointSize, color: bedMarkingsColor); for (double linePos = lineDist * (1 - fraction); linePos < bedplateImage.Width; linePos += lineDist) { xPositionCmInt++; int linePosInt = (int)linePos; int lineWidth = 1; if (xPositionCmInt == 0) { lineWidth = 2; } graphics2D.Line(linePosInt, 0, linePosInt, bedplateImage.Height, bedMarkingsColor, lineWidth); graphics2D.DrawString((xPositionCmInt * skip).ToString(), linePos + 4, 4, pointSize, color: bedMarkingsColor); } } { double lineDist = bedplateImage.Height / (displayVolumeToBuild.Y / divisor); double yPositionCm = (-(printer.Bed.ViewerVolume.Y / 2.0) + printer.Bed.BedCenter.Y) / divisor; int yPositionCmInt = (int)Math.Round(yPositionCm); double fraction = yPositionCm - yPositionCmInt; int pointSize = 20; for (double linePos = lineDist * (1 - fraction); linePos < bedplateImage.Height; linePos += lineDist) { yPositionCmInt++; int linePosInt = (int)linePos; int lineWidth = 1; if (yPositionCmInt == 0) { lineWidth = 2; } graphics2D.Line(0, linePosInt, bedplateImage.Height, linePosInt, bedMarkingsColor, lineWidth); graphics2D.DrawString((yPositionCmInt * skip).ToString(), 4, linePos + 4, pointSize, color: bedMarkingsColor); } } ApplyOemBedImage(bedplateImage, printer); return(bedplateImage); }
private static ImageBuffer CreateCircularBedGridImage(PrinterConfig printer) { var displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1)); double sizeForMarking = Math.Max(displayVolumeToBuild.X, displayVolumeToBuild.Y); double cmPerLine = 10; int skip = 1; if (sizeForMarking > 1000) { cmPerLine = 100; skip = 10; } else if (sizeForMarking > 300) { cmPerLine = 50; skip = 5; } var theme = AppContext.Theme; var bedMarkingsColor = theme.PrinterBedTextColor; var bedplateImage = new ImageBuffer(1024, 1024); Graphics2D graphics2D = bedplateImage.NewGraphics2D(); graphics2D.Clear(theme.BedColor); var originPixels = new Vector2(); { double lineSpacePixels = bedplateImage.Width / (displayVolumeToBuild.X / cmPerLine); double xPositionLines = (-(printer.Bed.ViewerVolume.X / 2.0) + printer.Bed.BedCenter.X) / cmPerLine; int xPositionCmInt = (int)Math.Round(xPositionLines); double fraction = xPositionLines - xPositionCmInt; for (double linePos = lineSpacePixels * (1 - fraction); linePos < bedplateImage.Width; linePos += lineSpacePixels) { xPositionCmInt++; if (xPositionCmInt == 0) { originPixels.X = linePos; } } } { double lineDist = bedplateImage.Height / (displayVolumeToBuild.Y / cmPerLine); double yPositionCm = (-(printer.Bed.ViewerVolume.Y / 2.0) + printer.Bed.BedCenter.Y) / cmPerLine; int yPositionCmInt = (int)Math.Round(yPositionCm); double fraction = yPositionCm - yPositionCmInt; for (double linePos = lineDist * (1 - fraction); linePos < bedplateImage.Height; linePos += lineDist) { yPositionCmInt++; int linePosInt = (int)linePos; if (yPositionCmInt == 0) { originPixels.Y = linePos; } } } var bedCircle = new Ellipse(bedplateImage.Width / 2, bedplateImage.Height / 2, bedplateImage.Width / 2, bedplateImage.Height / 2); graphics2D.Render(bedCircle, theme.BedColor); //graphics2D.Clear(bedBaseColor); { double lineSpacePixels = bedplateImage.Width / (displayVolumeToBuild.X / cmPerLine); double xPositionLines = (-(printer.Bed.ViewerVolume.X / 2.0) + printer.Bed.BedCenter.X) / cmPerLine; int xPositionCmInt = (int)Math.Round(xPositionLines); double fraction = xPositionLines - xPositionCmInt; int pointSize = 20; graphics2D.DrawString((xPositionCmInt * skip).ToString(), 4, originPixels.Y + 4, pointSize, color: bedMarkingsColor); for (double linePos = lineSpacePixels * (1 - fraction); linePos < bedplateImage.Width; linePos += lineSpacePixels) { xPositionCmInt++; int linePosInt = (int)linePos; int lineWidth = 1; if (xPositionCmInt == 0) { lineWidth = 2; graphics2D.Line(linePosInt, 0, linePosInt, bedplateImage.Height, bedMarkingsColor, lineWidth); } graphics2D.DrawString((xPositionCmInt * skip).ToString(), linePos + 4, originPixels.Y + 4, pointSize, color: bedMarkingsColor); var circle = new Ellipse(originPixels, linePos - originPixels.X); var outline = new Stroke(circle); graphics2D.Render(outline, bedMarkingsColor); } } { double lineDist = bedplateImage.Height / (displayVolumeToBuild.Y / cmPerLine); double yPositionCm = (-(printer.Bed.ViewerVolume.Y / 2.0) + printer.Bed.BedCenter.Y) / cmPerLine; int yPositionCmInt = (int)Math.Round(yPositionCm); double fraction = yPositionCm - yPositionCmInt; int pointSize = 20; for (double linePos = lineDist * (1 - fraction); linePos < bedplateImage.Height; linePos += lineDist) { yPositionCmInt++; int linePosInt = (int)linePos; int lineWidth = 1; if (yPositionCmInt == 0) { lineWidth = 2; originPixels.Y = linePos; graphics2D.Line(0, linePosInt, bedplateImage.Height, linePosInt, bedMarkingsColor, lineWidth); } graphics2D.DrawString((yPositionCmInt * skip).ToString(), originPixels.X + 4, linePos + 4, pointSize, color: bedMarkingsColor); } } ApplyOemBedImage(bedplateImage, printer); return(bedplateImage); }