diff --git a/MatterControl.Printing/Settings/PrinterSettings.cs b/MatterControl.Printing/Settings/PrinterSettings.cs index 2611978fc..cc06e9f0b 100644 --- a/MatterControl.Printing/Settings/PrinterSettings.cs +++ b/MatterControl.Printing/Settings/PrinterSettings.cs @@ -374,6 +374,46 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } } + /// + /// The bounds that a mesh can be placed at and the gcode it creates will be within the bed + /// + [JsonIgnore] + public RectangleDouble MeshAllowedBounds + { + get + { + var firstLayerExtrusionWidth = GetDouble(SettingsKey.first_layer_extrusion_width); + var bedBounds = BedBounds; + var totalOffset = 0.0; + + if (GetBool(SettingsKey.create_raft)) + { + // The slicing engine creates a raft 3x the extrusion width + firstLayerExtrusionWidth *= 3; + totalOffset += firstLayerExtrusionWidth; + totalOffset += GetDouble(SettingsKey.raft_extra_distance_around_part); + } + + if (GetBool(SettingsKey.create_skirt)) + { + totalOffset += GetValue(SettingsKey.skirt_distance); + totalOffset += (GetDouble(SettingsKey.skirts) + .5) * firstLayerExtrusionWidth; + // for every 400mm of min skirt length add another skirt loops + totalOffset += GetDouble(SettingsKey.min_skirt_length) / (20 * 20); + } + + if (GetBool(SettingsKey.create_brim) + && !GetBool(SettingsKey.create_raft)) + { + totalOffset += GetValue(SettingsKey.brims) * GetDouble(SettingsKey.first_layer_extrusion_width); + } + + bedBounds.Inflate(-totalOffset); + + return bedBounds; + } + } + [JsonIgnore] public IEnumerable DefaultLayerCascade { @@ -1176,6 +1216,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return GetValue(settingsKey); } + public double GetDouble(string settingsKey) + { + return GetValue(settingsKey); + } + /// /// Returns the first matching value discovered while enumerating the settings layers /// diff --git a/MatterControlLib/ApplicationView/PrinterExtensionMethods.cs b/MatterControlLib/ApplicationView/PrinterExtensionMethods.cs index c33513d6b..c171cf771 100644 --- a/MatterControlLib/ApplicationView/PrinterExtensionMethods.cs +++ b/MatterControlLib/ApplicationView/PrinterExtensionMethods.cs @@ -63,13 +63,15 @@ namespace MatterHackers.MatterControl return false; } + var bedBounds = printerConfig.Settings.MeshAllowedBounds; + switch (bed.BedShape) { case BedShape.Rectangular: - if (aabb.MinXYZ.X < bed.BedCenter.X - bed.ViewerVolume.X / 2 - || aabb.MaxXYZ.X > bed.BedCenter.X + bed.ViewerVolume.X / 2 - || aabb.MinXYZ.Y < bed.BedCenter.Y - bed.ViewerVolume.Y / 2 - || aabb.MaxXYZ.Y > bed.BedCenter.Y + bed.ViewerVolume.Y / 2) + if (aabb.MinXYZ.X < bedBounds.Left + || aabb.MaxXYZ.X > bedBounds.Right + || aabb.MinXYZ.Y < bedBounds.Bottom + || aabb.MaxXYZ.Y > bedBounds.Top) { return false; } diff --git a/MatterControlLib/ApplicationView/SceneOperations.cs b/MatterControlLib/ApplicationView/SceneOperations.cs index e8a789754..877b21f03 100644 --- a/MatterControlLib/ApplicationView/SceneOperations.cs +++ b/MatterControlLib/ApplicationView/SceneOperations.cs @@ -293,6 +293,8 @@ namespace MatterHackers.MatterControl var scene = sceneContext.Scene; var sceneItem = scene.SelectedItem; var imageObject = sceneItem.Clone() as ImageObject3D; + var finalMatrix = imageObject.Matrix; + imageObject.Matrix = Matrix4X4.Identity; var path = new ImageToPathObject3D_2(); path.Children.Add(imageObject); @@ -328,13 +330,11 @@ namespace MatterHackers.MatterControl } }; - component.Matrix = imageObject.Matrix; - imageObject.Matrix = Matrix4X4.Identity; + component.Matrix = finalMatrix; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { component })); - } + scene.SelectedItem = null; + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { component })); + scene.SelectedItem = component; // Invalidate image to kick off rebuild of ImageConverter stack imageObject.Invalidate(InvalidateType.Image); @@ -397,10 +397,10 @@ namespace MatterHackers.MatterControl inflatePath.Matrix = itemClone.Matrix; itemClone.Matrix = Matrix4X4.Identity; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { inflatePath })); - } + scene.SelectedItem = null; + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { inflatePath })); + scene.SelectedItem = inflatePath; + inflatePath.Invalidate(InvalidateType.Properties); }, @@ -430,10 +430,9 @@ namespace MatterHackers.MatterControl extrude.Matrix = itemClone.Matrix; itemClone.Matrix = Matrix4X4.Identity; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { extrude })); - } + scene.SelectedItem = null; + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { extrude })); + scene.SelectedItem = extrude; extrude.Invalidate(InvalidateType.Properties); } @@ -464,10 +463,9 @@ namespace MatterHackers.MatterControl revolve.Matrix = itemClone.Matrix; itemClone.Matrix = Matrix4X4.Identity; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { revolve })); - } + scene.SelectedItem = null; + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { revolve })); + scene.SelectedItem = revolve; revolve.Invalidate(InvalidateType.Properties); } @@ -497,24 +495,23 @@ namespace MatterHackers.MatterControl } // Dump selection forcing collapse of selection group - using (new DataConverters3D.SelectionMaintainer(scene)) + scene.SelectedItem = null; + var component = new ComponentObject3D { - var component = new ComponentObject3D - { - Name = "New Component", - Finalized = false - }; + Name = "New Component", + Finalized = false + }; - // Copy an selected item into the component as a clone - component.Children.Modify(children => - { - children.AddRange(items.Select(o => o.Clone())); - }); + // Copy an selected item into the component as a clone + component.Children.Modify(children => + { + children.AddRange(items.Select(o => o.Clone())); + }); - component.MakeNameNonColliding(); + component.MakeNameNonColliding(); - scene.UndoBuffer.AddAndDo(new ReplaceCommand(items, new[] { component })); - } + scene.UndoBuffer.AddAndDo(new ReplaceCommand(items, new[] { component })); + scene.SelectedItem = component; }, Icon = (theme) => StaticData.Instance.LoadIcon("component.png", 16, 16).SetToColor(theme.TextColor).SetPreMultiply(), HelpTextGetter = () => "At least 1 part must be selected".Localize().Stars(), @@ -562,10 +559,9 @@ namespace MatterHackers.MatterControl outlinePath.Matrix = itemClone.Matrix; itemClone.Matrix = Matrix4X4.Identity; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { outlinePath })); - } + scene.SelectedItem = null; + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { outlinePath })); + scene.SelectedItem = outlinePath; outlinePath.Invalidate(InvalidateType.Properties); }, @@ -626,10 +622,9 @@ namespace MatterHackers.MatterControl smoothPath.Matrix = itemClone.Matrix; itemClone.Matrix = Matrix4X4.Identity; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { smoothPath })); - } + scene.SelectedItem = null; + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { sceneItem }, new[] { smoothPath })); + scene.SelectedItem = smoothPath; smoothPath.Invalidate(InvalidateType.Properties); }, @@ -1039,13 +1034,11 @@ namespace MatterHackers.MatterControl { var scene = sceneContext.Scene; var selectedItem = scene.SelectedItem; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - var fit = await FitToBoundsObject3D_3.Create(selectedItem.Clone()); - fit.MakeNameNonColliding(); - - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { selectedItem }, new[] { fit })); - } + scene.SelectedItem = null; + var fit = await FitToBoundsObject3D_3.Create(selectedItem.Clone()); + fit.MakeNameNonColliding(); + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { selectedItem }, new[] { fit })); + scene.SelectedItem = fit; }, Icon = (theme) => StaticData.Instance.LoadIcon("fit.png", 16, 16).SetToColor(theme.TextColor), IsEnabled = (sceneContext) => sceneContext.Scene.SelectedItem != null && !(sceneContext.Scene.SelectedItem is SelectionGroupObject3D), @@ -1063,13 +1056,11 @@ namespace MatterHackers.MatterControl { var scene = sceneContext.Scene; var selectedItem = scene.SelectedItem; - using (new DataConverters3D.SelectionMaintainer(scene)) - { - var fit = await FitToCylinderObject3D.Create(selectedItem.Clone()); - fit.MakeNameNonColliding(); - - scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { selectedItem }, new[] { fit })); - } + scene.SelectedItem = null; + var fit = await FitToCylinderObject3D.Create(selectedItem.Clone()); + fit.MakeNameNonColliding(); + scene.UndoBuffer.AddAndDo(new ReplaceCommand(new[] { selectedItem }, new[] { fit })); + scene.SelectedItem = fit; }, Icon = (theme) => StaticData.Instance.LoadIcon("fit.png", 16, 16).SetToColor(theme.TextColor), IsEnabled = (sceneContext) => sceneContext.Scene.SelectedItem != null && !(sceneContext.Scene.SelectedItem is SelectionGroupObject3D), diff --git a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleDiameterControl.cs b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleDiameterControl.cs index 7a3ed509f..3d3afe0a6 100644 --- a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleDiameterControl.cs +++ b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleDiameterControl.cs @@ -180,7 +180,7 @@ namespace MatterHackers.Plugins.EditorTools return false; } - return true; + return shouldDrawScaleControls; } private Matrix4X4 GetRingTransform() diff --git a/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs b/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs index 0abb709cd..1b8b31dce 100644 --- a/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs @@ -30,12 +30,11 @@ either expressed or implied, of the FreeBSD Project. using System.Collections.Generic; using System.ComponentModel; using System.Linq; -using MatterHackers.Agg; +using System.Threading; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.DataConverters3D.UndoCommands; using MatterHackers.Localizations; -using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.DesignTools.Operations; namespace MatterHackers.MatterControl.DesignTools @@ -134,7 +133,89 @@ namespace MatterHackers.MatterControl.DesignTools Invalidate(InvalidateType.Children); } - public override void Cancel(UndoBuffer undoBuffer) + public (string cellId, string cellData) DecodeContent(int editorIndex) + { + var cellData2 = SurfacedEditors[editorIndex].Substring(1); + var cellId2 = cellData2.ToLower(); + // check if it has embededdata + var separator = cellData2.IndexOf(','); + if (separator != -1) + { + cellId2 = cellData2.Substring(0, separator).ToLower(); + cellData2 = cellData2.Substring(separator + 1); + } + else + { + var firtSheet = this.Descendants().FirstOrDefault(); + if (firtSheet != null) + { + // We don't have any cache of the cell content, get the current content + double.TryParse(firtSheet.SheetData.EvaluateExpression(cellId2), out double value); + cellData2 = value.ToString(); + } + } + + return (cellId2, cellData2); + } + + + private void RecalculateSheet() + { + // if there are editors that reference cells + for (int i=0; i().FirstOrDefault(); + + var componentLock = this.RebuildLock(); + firtSheet.SheetData.Recalculate(); + + UiThread.RunOnIdle(() => + { + // wait until the sheet is done rebuilding (or 30 seconds) + var startTime = UiThread.CurrentTimerMs; + while (firtSheet.RebuildLocked + && startTime + 30000 < UiThread.CurrentTimerMs) + { + Thread.Sleep(1); + } + + componentLock.Dispose(); + }); + } + } + + public override void OnInvalidate(InvalidateArgs invalidateType) + { + switch(invalidateType.InvalidateType) + { + case InvalidateType.SheetUpdated: + RecalculateSheet(); + break; + } + + base.OnInvalidate(invalidateType); + } + + public override void Cancel(UndoBuffer undoBuffer) { // Make any hiden children visible // on any invalidate ensure that the visibility setting are correct for embedded sheet objects diff --git a/MatterControlLib/Library/Export/GCodeExport.cs b/MatterControlLib/Library/Export/GCodeExport.cs index d56e63eee..a328c5f73 100644 --- a/MatterControlLib/Library/Export/GCodeExport.cs +++ b/MatterControlLib/Library/Export/GCodeExport.cs @@ -170,7 +170,8 @@ namespace MatterHackers.MatterControl.Library.Export { this.ApplyStreamPipelineAndExport( new GCodeFileStream(new GCodeFileStreamed(gcodeStream.Stream), Printer), - outputPath); + outputPath, + progress); return null; } @@ -266,7 +267,7 @@ namespace MatterHackers.MatterControl.Library.Export if (File.Exists(gcodePath)) { - ApplyStreamPipelineAndExport(gcodePath, outputPath); + ApplyStreamPipelineAndExport(gcodePath, outputPath, progress); return errors; } } @@ -339,12 +340,20 @@ namespace MatterHackers.MatterControl.Library.Export return accumulatedStream; } - private void ApplyStreamPipelineAndExport(GCodeFileStream gCodeFileStream, string outputPath) + private void ApplyStreamPipelineAndExport(GCodeFileStream gCodeFileStream, string outputPath, IProgress progress) { try { var finalStream = GetExportStream(Printer, gCodeFileStream, UserSettings.Instance.GetValue(UserSettingsKey.ApplyLevelingDurringExport, "1")); + var totalLines = gCodeFileStream.GCodeFile.LineCount; + var currentLine = 0; + + var status = new ProgressStatus() + { + Status = "Writing G-Code".Localize() + }; + // Run each line from the source gcode through the loaded pipeline and dump to the output location using (var file = new StreamWriter(outputPath)) { @@ -375,6 +384,13 @@ namespace MatterHackers.MatterControl.Library.Export PrinterConnection.KeepTrackOfAbsolutePositionAndDestination(nextLine, ref currentDestination); } + + if (currentLine % 1024 == 0) + { + status.Progress0To1 = currentLine / (double)totalLines; + progress.Report(status); + } + currentLine++; } } } @@ -387,7 +403,7 @@ namespace MatterHackers.MatterControl.Library.Export } } - private void ApplyStreamPipelineAndExport(string gcodeFilename, string outputPath) + private void ApplyStreamPipelineAndExport(string gcodeFilename, string outputPath, IProgress progress) { try { @@ -407,7 +423,8 @@ namespace MatterHackers.MatterControl.Library.Export new Vector4(multiplier, multiplier, multiplier, multiplier), CancellationToken.None), Printer), - outputPath); + outputPath, + progress); } catch (Exception e) { diff --git a/MatterControlLib/Library/Widgets/AddMaterialWidget.cs b/MatterControlLib/Library/Widgets/AddMaterialWidget.cs index fd1397361..b9871cd41 100644 --- a/MatterControlLib/Library/Widgets/AddMaterialWidget.cs +++ b/MatterControlLib/Library/Widgets/AddMaterialWidget.cs @@ -206,6 +206,11 @@ namespace MatterHackers.MatterControl.Library.Widgets }); } + if (directory.Contains("MatterHackers")) + { + treeNode.Expanded = true; + } + return treeNode; } diff --git a/MatterControlLib/Library/Widgets/HardwarePage/PrinterDetails.cs b/MatterControlLib/Library/Widgets/HardwarePage/PrinterDetails.cs index a4a9d021d..85df6f698 100644 --- a/MatterControlLib/Library/Widgets/HardwarePage/PrinterDetails.cs +++ b/MatterControlLib/Library/Widgets/HardwarePage/PrinterDetails.cs @@ -107,21 +107,31 @@ namespace MatterHackers.MatterControl.Library.Widgets.HardwarePage } } + // add a section to hold the data about the printer + var scrollableWidget = new ScrollableWidget(true); + scrollableWidget.ScrollArea.HAnchor |= HAnchor.Stretch; + scrollableWidget.ScrollArea.VAnchor = VAnchor.Fit; + scrollableWidget.AnchorAll(); + + scrollableWidget.AddChild(ProductDataContainer = new FlowLayoutWidget(FlowDirection.TopToBottom) + { + HAnchor = HAnchor.Stretch + }); + + this.AddChild(scrollableWidget); + + void DoAfterLoad() + { + AfterLoad?.Invoke(this, null); + + scrollableWidget.Width += 1; + scrollableWidget.Width -= 1; + + scrollableWidget.TopLeftOffset = new Vector2(0, 0); + } + if (!string.IsNullOrWhiteSpace(StoreID)) { - // add a section to hold the data about the printer - var scrollableWidget = new ScrollableWidget(true); - scrollableWidget.ScrollArea.HAnchor |= HAnchor.Stretch; - scrollableWidget.ScrollArea.VAnchor = VAnchor.Fit; - scrollableWidget.AnchorAll(); - - scrollableWidget.AddChild(ProductDataContainer = new FlowLayoutWidget(FlowDirection.TopToBottom) - { - HAnchor = HAnchor.Stretch - }); - - this.AddChild(scrollableWidget); - try { // put in controls from the feed that show relevant printer information @@ -164,12 +174,7 @@ namespace MatterHackers.MatterControl.Library.Widgets.HardwarePage } } - AfterLoad?.Invoke(this, null); - - scrollableWidget.Width += 1; - scrollableWidget.Width -= 1; - - scrollableWidget.TopLeftOffset = new Vector2(0, 0); + DoAfterLoad(); }); }); } @@ -178,6 +183,10 @@ namespace MatterHackers.MatterControl.Library.Widgets.HardwarePage Trace.WriteLine("Error collecting or loading printer details: " + ex.Message); } } + else + { + DoAfterLoad(); + } headingRow.Visible = this.ShowHeadingRow; diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index c92fe3ba7..f2ae36720 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -348,101 +348,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow // put in the normal editor if (selectedItem is ComponentObject3D componentObject && componentObject.Finalized) - { - var context = new PPEContext(); - PublicPropertyEditor.AddUnlockLinkIfRequired(selectedItem, editorPanel, theme); - foreach (var selector in componentObject.SurfacedEditors) - { - // if it is a reference to a sheet cell - if (selector.StartsWith("!")) - { - var firtSheet = componentObject.Descendants().FirstOrDefault(); - if (firtSheet != null) - { - var cellId = selector.Substring(1).ToLower(); - var cell = firtSheet.SheetData[cellId]; - if (cell != null) - { - // add an editor for the cell - var field = new DoubleField(theme); - field.Initialize(0); - double.TryParse(firtSheet.SheetData.EvaluateExpression(cellId), out double value); - field.DoubleValue = value; - field.ClearUndoHistory(); - - field.Content.Descendants().First().MaxDecimalsPlaces = 3; - field.ValueChanged += (s, e) => - { - var oldValue = cell.Expression; - var newValue = field.Value; - undoBuffer.AddAndDo(new UndoRedoActions(() => - { - cell.Expression = oldValue; - firtSheet.SheetData.Recalculate(); - }, - () => - { - cell.Expression = newValue; - firtSheet.SheetData.Recalculate(); - })); - - }; - - var row = new SettingsRow(cell.Name == null ? cellId : cell.Name, null, field.Content, theme); - - editorPanel.AddChild(row); - } - } - } - else // parse it as a path to an object - { - // Get the named property via reflection - // Selector example: '$.Children' - var match = pathGetter.Select(componentObject, selector).ToList(); - - //// - Add editor row for each - foreach (var instance in match) - { - if (instance is IObject3D object3D) - { - if (ApplicationController.Instance.Extensions.GetEditorsForType(object3D.GetType())?.FirstOrDefault() is IObject3DEditor editor) - { - ShowObjectEditor((editor, object3D, object3D.Name), selectedItem); - } - } - else if (JsonPathContext.ReflectionValueSystem.LastMemberValue is ReflectionTarget reflectionTarget) - { - if (reflectionTarget.Source is IObject3D editedChild) - { - context.item = editedChild; - } - else - { - context.item = item; - } - - var editableProperty = new EditableProperty(reflectionTarget.PropertyInfo, reflectionTarget.Source); - - var editor = PublicPropertyEditor.CreatePropertyEditor(rows, editableProperty, undoBuffer, context, theme); - if (editor != null) - { - editorPanel.AddChild(editor); - } - - // Init with custom 'UpdateControls' hooks - (context.item as IPropertyGridModifier)?.UpdateControls(new PublicPropertyChange(context, "Update_Button")); - } - } - } - } - - // Enforce panel padding - foreach (var sectionWidget in editorPanel.Descendants()) - { - sectionWidget.Margin = 0; - } - } - else + { + AddComponentEditor(selectedItem, undoBuffer, rows, componentObject); + } + else { if (item != null && ApplicationController.Instance.Extensions.GetEditorsForType(item.GetType())?.FirstOrDefault() is IObject3DEditor editor) @@ -452,7 +361,131 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - private class OperationButton : TextButton + private void AddComponentEditor(IObject3D selectedItem, UndoBuffer undoBuffer, SafeList rows, ComponentObject3D componentObject) + { + var context = new PPEContext(); + PublicPropertyEditor.AddUnlockLinkIfRequired(selectedItem, editorPanel, theme); + var editorList = componentObject.SurfacedEditors; + for (var editorIndex = 0; editorIndex < editorList.Count; editorIndex++) + { + // if it is a reference to a sheet cell + if (editorList[editorIndex].StartsWith("!")) + { + AddSheetCellEditor(undoBuffer, componentObject, editorList, editorIndex); + } + else // parse it as a path to an object + { + // Get the named property via reflection + // Selector example: '$.Children' + var match = pathGetter.Select(componentObject, editorList[editorIndex]).ToList(); + + //// - Add editor row for each + foreach (var instance in match) + { + if (instance is IObject3D object3D) + { + if (ApplicationController.Instance.Extensions.GetEditorsForType(object3D.GetType())?.FirstOrDefault() is IObject3DEditor editor) + { + ShowObjectEditor((editor, object3D, object3D.Name), selectedItem); + } + } + else if (JsonPathContext.ReflectionValueSystem.LastMemberValue is ReflectionTarget reflectionTarget) + { + if (reflectionTarget.Source is IObject3D editedChild) + { + context.item = editedChild; + } + else + { + context.item = item; + } + + var editableProperty = new EditableProperty(reflectionTarget.PropertyInfo, reflectionTarget.Source); + + var editor = PublicPropertyEditor.CreatePropertyEditor(rows, editableProperty, undoBuffer, context, theme); + if (editor != null) + { + editorPanel.AddChild(editor); + } + + // Init with custom 'UpdateControls' hooks + (context.item as IPropertyGridModifier)?.UpdateControls(new PublicPropertyChange(context, "Update_Button")); + } + } + } + } + + // Enforce panel padding + foreach (var sectionWidget in editorPanel.Descendants()) + { + sectionWidget.Margin = 0; + } + } + + private void AddSheetCellEditor(UndoBuffer undoBuffer, ComponentObject3D componentObject, List editorList, int editorIndex) + { + var firtSheet = componentObject.Descendants().FirstOrDefault(); + if (firtSheet != null) + { + var (cellId, cellData) = componentObject.DecodeContent(editorIndex); + var cell = firtSheet.SheetData[cellId]; + if (cell != null) + { + // create an expresion editor + var field = new ExpressionField(theme) + { + Name = cellId + " Field" + }; + field.Initialize(0); + if (cellData.Contains("=")) + { + field.SetValue(cellData, false); + } + else // make sure it is formatted + { + double.TryParse(cellData, out double value); + var format = "0." + new string('#', 5); + field.SetValue(value.ToString(format), false); + } + + field.ClearUndoHistory(); + + var doOrUndoing = false; + field.ValueChanged += (s, e) => + { + if (!doOrUndoing) + { + var oldValue = componentObject.DecodeContent(editorIndex).cellData; + var newValue = field.Value; + undoBuffer.AddAndDo(new UndoRedoActions(() => + { + doOrUndoing = true; + editorList[editorIndex] = "!" + cellId + "," + oldValue; + var expression = new DoubleOrExpression(oldValue); + cell.Expression = expression.Value(componentObject).ToString(); + componentObject.Invalidate(InvalidateType.SheetUpdated); + doOrUndoing = false; + }, + () => + { + doOrUndoing = true; + editorList[editorIndex] = "!" + cellId + "," + newValue; + var expression = new DoubleOrExpression(newValue); + cell.Expression = expression.Value(componentObject).ToString(); + componentObject.Invalidate(InvalidateType.SheetUpdated); + doOrUndoing = false; + })); + } + + }; + + var row = new SettingsRow(cell.Name == null ? cellId : cell.Name, null, field.Content, theme); + editorPanel.AddChild(row); + } + } + } + + private class OperationButton : TextButton { private readonly SceneOperation sceneOperation; private readonly ISceneContext sceneContext; diff --git a/MatterControlLib/PartPreviewWindow/View3D/Object3DControlsLayer.cs b/MatterControlLib/PartPreviewWindow/View3D/Object3DControlsLayer.cs index 86a0dfac4..836833144 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Object3DControlsLayer.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Object3DControlsLayer.cs @@ -1283,14 +1283,20 @@ namespace MatterHackers.MatterControl.PartPreviewWindow foreach (var ctrl in scene.Descendants()) { if (ctrl is ICustomEditorDraw customEditorDraw1 && customEditorDraw1.DoEditorDraw(ctrl == selectedItem)) + { if (ctrl is IEditorDraw editorDraw2) + { aabbs.Add(editorDraw2.GetEditorWorldspaceAABB(this)); + } + } } foreach (var ctrl in drawables) { if (ctrl.Enabled) + { aabbs.Add(ctrl.GetWorldspaceAABB()); + } } foreach (var obj in scene.Children) diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index f688577bd..5d4d04ebf 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -26,18 +26,15 @@ The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -#define INCLUDE_ORTHOGRAPHIC #define ENABLE_PERSPECTIVE_PROJECTION_DYNAMIC_NEAR_FAR using AngleSharp.Dom; using AngleSharp.Html.Parser; using MatterHackers.Agg; -using MatterHackers.Agg.Image; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.Agg.VertexSource; using MatterHackers.DataConverters3D; -using MatterHackers.DataConverters3D.UndoCommands; using MatterHackers.ImageProcessing; using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; @@ -440,9 +437,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow renderRoundedGroup(.1, .5 + .1); // render the perspective and turntable group background -#if INCLUDE_ORTHOGRAPHIC renderRoundedGroup(.1, 1 - .1); // when we have both ortho and turntable -#endif void renderRoundedLine(double lineWidth, double heightBelowCenter) { @@ -504,16 +499,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow SiblingRadioButtonList = new List(), Checked = turntableEnabled, //DoubleBuffer = true, -#if !INCLUDE_ORTHOGRAPHIC - BorderColor = hudStrokeColor, -#endif }; -#if INCLUDE_ORTHOGRAPHIC AddRoundButton(turnTableButton, RotatedMargin(turnTableButton, -MathHelper.Tau * .4)); // 2 button position -#else - AddRoundButton(turnTableButton, RotatedMargin(turnTableButton, -MathHelper.Tau * .30)); -#endif turnTableButton.CheckedStateChanged += (s, e) => { UserSettings.Instance.set(UserSettingsKey.TurntableMode, turnTableButton.Checked.ToString()); @@ -526,7 +514,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } }; -#if INCLUDE_ORTHOGRAPHIC var perspectiveEnabled = UserSettings.Instance.get(UserSettingsKey.PerspectiveMode) != false.ToString(); TrackballTumbleWidget.ChangeProjectionMode(perspectiveEnabled, false); var projectionButton = new RadioIconButton(StaticData.Instance.LoadIcon("perspective.png", 16, 16).SetToColor(theme.TextColor), theme) @@ -552,7 +539,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow Invalidate(); }; -#endif var startHeight = 180; var ySpacing = 40; @@ -913,7 +899,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow private void UpdateRenderView(object sender, EventArgs e) { - TrackballTumbleWidget.CenterOffsetX = -modelViewSidePanel.Width; + UiThread.RunOnUiThread(() => TrackballTumbleWidget.CenterOffsetX = -modelViewSidePanel.Width); } private void SceneContext_SceneLoaded(object sender, EventArgs e) diff --git a/StaticData/Materials/3DXTech/PEEK-A.material b/StaticData/Materials/3DXTech/PEEK-A.material new file mode 100644 index 000000000..b0b949096 --- /dev/null +++ b/StaticData/Materials/3DXTech/PEEK-A.material @@ -0,0 +1,32 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "PEEK", + "layer_id": "63342beb-0f41-4afb-bf96-bf73bd168bd7", + "bed_temperature": "130", + "bridge_fan_speed": "50", + "max_fan_speed": "0", + "min_fan_speed": "0", + "temperature": "360", + "infill_speed": "60", + "top_solid_infill_speed": "20", + "perimeter_speed": "20", + "bed_temperature_buildtak": "130", + "bed_temperature_garolite": "130", + "bed_temperature_glass": "130", + "bed_temperature_kapton": "130", + "bed_temperature_pei": "130", + "bed_temperature_pp": "130", + "external_perimeter_speed": "20", + "enable_fan": "0", + "material_sku": "MRM86607" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/3DXTech/ezPC.material b/StaticData/Materials/3DXTech/ezPC.material new file mode 100644 index 000000000..37543ad73 --- /dev/null +++ b/StaticData/Materials/3DXTech/ezPC.material @@ -0,0 +1,30 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "3DXTech ezPC", + "layer_id": "d9240109-d750-462a-9d72-4c4f53678710", + "bed_temperature": "115", + "enable_fan": "0", + "infill_speed": "30", + "max_fan_speed": "0", + "min_fan_speed": "0", + "perimeter_speed": "26", + "temperature": "290", + "bed_temperature_buildtak": "110", + "bed_temperature_garolite": "110", + "bed_temperature_glass": "110", + "bed_temperature_kapton": "110", + "bed_temperature_pei": "110", + "bed_temperature_pp": "110", + "top_solid_infill_speed": "22", + "material_sku": "M1JH1UAQ" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/BASF/ABS Fusion.material b/StaticData/Materials/BASF/ABS Fusion.material new file mode 100644 index 000000000..c5f4c802c --- /dev/null +++ b/StaticData/Materials/BASF/ABS Fusion.material @@ -0,0 +1,33 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "BASF ABS Fusion+", + "filament_density": "1.04", + "layer_id": "2bcc7c0a-2275-4e30-ae4e-e24b3acea1a2", + "bed_temperature": "100", + "temperature": "240", + "min_fan_speed": "70", + "max_fan_speed": "100", + "bridge_fan_speed": "50", + "enable_fan": "0", + "filament_cost": "42", + "min_fan_speed_layer_time": "8", + "max_fan_speed_layer_time": "8", + "disable_fan_first_layers": "5", + "bed_temperature_buildtak": "100", + "bed_temperature_garolite": "100", + "bed_temperature_glass": "100", + "bed_temperature_kapton": "100", + "bed_temperature_pei": "100", + "bed_temperature_pp": "100", + "material_sku": "MU25ZAEV" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/BASF/PRO1 Tough PLA.material b/StaticData/Materials/BASF/PRO1 Tough PLA.material new file mode 100644 index 000000000..b9c3a29fc --- /dev/null +++ b/StaticData/Materials/BASF/PRO1 Tough PLA.material @@ -0,0 +1,29 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "BASF PRO1 Tough PLA", + "layer_id": "42348031-fadf-4e93-bfbc-6b5e78a9ad39", + "temperature": "220", + "bed_temperature": "55", + "min_fan_speed_layer_time": "180", + "max_fan_speed_layer_time": "60", + "min_fan_speed": "60", + "disable_fan_first_layers": "5", + "filament_cost": "42", + "bed_temperature_buildtak": "55", + "bed_temperature_garolite": "70", + "bed_temperature_glass": "70", + "bed_temperature_kapton": "55", + "bed_temperature_pei": "70", + "bed_temperature_pp": "55", + "material_sku": "MZ2HXEPK" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/BASF/Ultrafuse 17-4 PH.material b/StaticData/Materials/BASF/Ultrafuse 17-4 PH.material new file mode 100644 index 000000000..860fa4e2a --- /dev/null +++ b/StaticData/Materials/BASF/Ultrafuse 17-4 PH.material @@ -0,0 +1,41 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "BASF 17-4 PH", + "layer_id": "1238d9d9-76b9-44af-3457-a349ba27151f", + "enable_fan": "0", + "retract_lift": "1", + "filament_cost": "465", + "temperature": "240", + "bed_temperature": "100", + "bed_temperature_buildtak": "100", + "bed_temperature_garolite": "100", + "bed_temperature_glass": "100", + "bed_temperature_kapton": "100", + "bed_temperature_pei": "100", + "bed_temperature_pp": "100", + "filament_density": "7851", + "fill_density": "100%", + "infill_type": "LINES", + "perimeter_start_end_overlap": "50", + "infill_overlap_perimeter": "50%", + "first_layer_speed": "18", + "infill_speed": "35", + "top_solid_infill_speed": "25", + "perimeter_speed": "30", + "support_material_speed": "30", + "interface_layer_speed": "30", + "air_gap_speed": "30", + "bridge_speed": "18", + "min_print_speed": "10", + "material_sku": "MA27ESD5" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/General/PC.material b/StaticData/Materials/General/PC.material new file mode 100644 index 000000000..80c266546 --- /dev/null +++ b/StaticData/Materials/General/PC.material @@ -0,0 +1,31 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "Polycarbonate", + "layer_id": "d924b109-d750-4a2a-9d72-4c4f53178710", + "bed_temperature": "115", + "enable_fan": "0", + "has_fan": "False", + "infill_speed": "30", + "max_fan_speed": "0", + "min_fan_speed": "0", + "perimeter_speed": "26", + "temperature": "290", + "bed_temperature_buildtak": "100", + "bed_temperature_garolite": "100", + "bed_temperature_glass": "100", + "bed_temperature_kapton": "100", + "bed_temperature_pei": "100", + "bed_temperature_pp": "100", + "top_solid_infill_speed": "22", + "material_sku": "PC" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/General/TPU.material b/StaticData/Materials/General/TPU.material new file mode 100644 index 000000000..238a01fb3 --- /dev/null +++ b/StaticData/Materials/General/TPU.material @@ -0,0 +1,36 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "TPU", + "filament_density": "1.23", + "layer_id": "80357dda-abc1-4837-be45-54912ce1071d", + "first_layer_speed": "15", + "filament_cost": "24.64", + "infill_speed": "25", + "top_solid_infill_speed": "25", + "perimeter_speed": "25", + "support_material_speed": "25", + "interface_layer_speed": "25", + "air_gap_speed": "25", + "raft_print_speed": "25", + "enable_retractions": "0", + "temperature": "245", + "external_perimeter_speed": "25", + "min_print_speed": "25", + "bed_temperature_buildtak": "55", + "bed_temperature_garolite": "55", + "bed_temperature_glass": "65", + "bed_temperature_kapton": "65", + "bed_temperature_pei": "55", + "min_fan_speed": "0", + "material_sku": "TPU" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/_MatterHackers/Build Series/Silky PLA.material b/StaticData/Materials/_MatterHackers/Build Series/Silky PLA.material new file mode 100644 index 000000000..544f428aa --- /dev/null +++ b/StaticData/Materials/_MatterHackers/Build Series/Silky PLA.material @@ -0,0 +1,32 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "Build Series Silky PLA", + "filament_density": "1.24", + "layer_id": "74673ff2-0dde-4808-bd9d-06c23e137dfe", + "bed_temperature": "75", + "temperature": "215", + "min_fan_speed": "70", + "max_fan_speed": "100", + "bridge_fan_speed": "100", + "filament_cost": "24.99", + "min_fan_speed_layer_time": "180", + "max_fan_speed_layer_time": "60", + "disable_fan_first_layers": "5", + "bed_temperature_buildtak": "50", + "bed_temperature_garolite": "75", + "bed_temperature_glass": "75", + "bed_temperature_kapton": "50", + "bed_temperature_pei": "75", + "bed_temperature_pp": "75", + "material_sku": "M7KY4RCN" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/_MatterHackers/Build Series/TPU.material b/StaticData/Materials/_MatterHackers/Build Series/TPU.material new file mode 100644 index 000000000..df7e6d873 --- /dev/null +++ b/StaticData/Materials/_MatterHackers/Build Series/TPU.material @@ -0,0 +1,36 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "TPU", + "filament_density": "1.23", + "layer_id": "80657dda-a7c1-4837-be45-54990ce1071d", + "first_layer_speed": "15", + "filament_cost": "24.64", + "infill_speed": "25", + "top_solid_infill_speed": "25", + "perimeter_speed": "25", + "support_material_speed": "25", + "interface_layer_speed": "25", + "air_gap_speed": "25", + "raft_print_speed": "25", + "enable_retractions": "0", + "temperature": "245", + "external_perimeter_speed": "25", + "min_print_speed": "25", + "bed_temperature_buildtak": "55", + "bed_temperature_garolite": "55", + "bed_temperature_glass": "65", + "bed_temperature_kapton": "65", + "bed_temperature_pei": "55", + "min_fan_speed": "0", + "material_sku": "MWDVWSZ3" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/_MatterHackers/NylonG.material b/StaticData/Materials/_MatterHackers/NylonG.material index 720c9dded..d94e77b21 100644 --- a/StaticData/Materials/_MatterHackers/NylonG.material +++ b/StaticData/Materials/_MatterHackers/NylonG.material @@ -6,8 +6,8 @@ { "layer_name": "NylonG", "layer_id": "f8bf5181-0d9a-47ac-b8dd-c6ff6e24dc57", - "temperature": "255", - "bed_temperature": "60", + "temperature": "265", + "bed_temperature": "70", "filament_density": "1.01", "filament_cost": "64", "min_fan_speed": "35", @@ -18,9 +18,9 @@ "max_fan_speed_layer_time": "10", "layer_etag": "", "layer_source": "", - "bed_temperature_buildtak": "60", - "bed_temperature_garolite": "75", - "bed_temperature_glass": "75", + "bed_temperature_buildtak": "70", + "bed_temperature_garolite": "80", + "bed_temperature_glass": "85", "bed_temperature_kapton": "60", "bed_temperature_pei": "75", "bed_temperature_pp": "60", diff --git a/StaticData/Materials/_MatterHackers/NylonK.material b/StaticData/Materials/_MatterHackers/NylonK.material new file mode 100644 index 000000000..b016ae08c --- /dev/null +++ b/StaticData/Materials/_MatterHackers/NylonK.material @@ -0,0 +1,34 @@ +{ + "DocumentVersion": 201606271, + "ID": null, + "Macros": [], + "MaterialLayers": [ + { + "layer_name": "NylonK", + "layer_id": "f8235181-0d9a-47ac-b3dd-c6ff1224dc57", + "temperature": "265", + "bed_temperature": "70", + "filament_density": "1.01", + "filament_cost": "64", + "min_fan_speed": "35", + "max_fan_speed": "100", + "raft_fan_speed_percent": "0", + "bridge_fan_speed": "50", + "min_fan_speed_layer_time": "10", + "max_fan_speed_layer_time": "10", + "layer_etag": "", + "layer_source": "", + "bed_temperature_buildtak": "70", + "bed_temperature_garolite": "80", + "bed_temperature_glass": "85", + "bed_temperature_kapton": "60", + "bed_temperature_pei": "75", + "bed_temperature_pp": "60", + "material_sku": "MXTJFMYQ" + } + ], + "OemLayer": null, + "QualityLayers": [], + "StagedUserSettings": {}, + "UserLayer": {} +} \ No newline at end of file diff --git a/StaticData/Materials/_MatterHackers/NylonX.material b/StaticData/Materials/_MatterHackers/NylonX.material index ec4e372bf..bc1522e73 100644 --- a/StaticData/Materials/_MatterHackers/NylonX.material +++ b/StaticData/Materials/_MatterHackers/NylonX.material @@ -6,8 +6,8 @@ { "layer_name": "NylonX", "layer_id": "9c66e529-0034-407e-baa2-e4bb2d1fa0b8", - "temperature": "255", - "bed_temperature": "60", + "temperature": "265", + "bed_temperature": "70", "filament_density": "1.01", "filament_cost": "51.04", "min_fan_speed": "35", diff --git a/StaticData/Translations/Master.txt b/StaticData/Translations/Master.txt index cde59e2d0..dedd6a91d 100644 --- a/StaticData/Translations/Master.txt +++ b/StaticData/Translations/Master.txt @@ -6052,6 +6052,9 @@ Translated:Wouldn’t Slice Correctly English:Write Filter Translated:Write Filter +English:Writing G-Code +Translated:Writing G-Code + English:X and Y Distance Translated:X and Y Distance diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 0511fb98b..6c99f1203 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 0511fb98bd18e41c90ad149e7c9d33bc3c1d7d9e +Subproject commit 6c99f1203e518096aab007e18c7dc068fb41affe diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 67f89b06f..068334475 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 67f89b06fe709544b528c38037f2f3a878bea401 +Subproject commit 0683344758e8784f1ce10fb51b34dcf0a1c3c158 diff --git a/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs b/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs index 780db9e1e..46eeace1a 100644 --- a/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/OemProfileTests.cs @@ -4,8 +4,10 @@ using System.IO; using System.Linq; using MatterHackers.Agg; using MatterHackers.Agg.Platform; +using MatterHackers.MatterControl; using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.MatterControl.Tests.Automation; +using Newtonsoft.Json; using NUnit.Framework; namespace MatterControl.Tests.MatterControl @@ -191,13 +193,14 @@ M300 S3000 P30 ; Resume Tone"; var allMaterialIds = new HashSet(); - foreach(var profile in profiles) + for(var i = 0; i < profiles.Count; i++) { + var profile = profiles[i]; Assert.AreEqual(1, profile.MaterialLayers.Count, "Each material profile should have 1 material in it"); var material = profile.MaterialLayers[0]; profile.ActiveMaterialKey = material.LayerID; - Assert.IsTrue(!string.IsNullOrEmpty(profile.GetValue(SettingsKey.material_sku))); - Assert.IsTrue(!allMaterialIds.Contains(material.LayerID), "Every material needs a unique Id"); + Assert.IsTrue(!string.IsNullOrEmpty(profile.GetValue(SettingsKey.material_sku)), $"All profiles should have a material_sku set {files[i].FullName}"); + Assert.IsTrue(!allMaterialIds.Contains(material.LayerID), $"Every material needs a unique Id {files[i].FullName}"); allMaterialIds.Add(material.LayerID); } } @@ -329,6 +332,24 @@ M300 S3000 P30 ; Resume Tone"; // Must be a CSV and have only two values Assert.AreEqual(2, segments.Length, "[print_center] should have two values separated by a comma: " + printer.RelativeFilePath); + +#if false + // save out the material settings + foreach(var materialLayer in settings.MaterialLayers) + { + // create an empyt profile + var materialSettings = new PrinterSettings(); + // copy just this material setting to it + materialSettings.MaterialLayers.Add(materialLayer.Clone()); + // save it + var fileName = ApplicationController.Instance.SanitizeFileName(materialLayer.Name); + if (!string.IsNullOrEmpty(fileName)) + { + fileName = Path.Combine(@"C:\temp", "materials", fileName) + ".material"; + File.WriteAllText(fileName, JsonConvert.SerializeObject(materialSettings, Formatting.Indented)); + } + } +#endif }); }