Merge branch 'smash_1.7.1' into design_tools

# Conflicts:
#	PartPreviewWindow/View3D/View3DWidget.cs
#	SlicerConfiguration/SliceSettingsWidget.cs
#	SlicerConfiguration/SlicingQueue.cs
#	StaticData/SliceSettings/Properties.json
This commit is contained in:
Lars Brubaker 2017-05-19 14:56:16 -07:00
commit 352eb792f1
63 changed files with 30032 additions and 26547 deletions

View file

@ -34,6 +34,7 @@ using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.MatterControl.SlicerConfiguration;
@ -218,7 +219,13 @@ namespace MatterHackers.MatterControl.ActionBar
doneWithCurrentPartButton = makeButton("Done".Localize(), "Move to next print in queue".Localize());
doneWithCurrentPartButton.Name = "Done Button";
doneWithCurrentPartButton.Click += onDoneWithCurrentPartButton_Click;
doneWithCurrentPartButton.Click += (s,e) => UiThread.RunOnIdle(() =>
{
PrinterConnectionAndCommunication.Instance.ResetToReadyState();
QueueData.Instance.RemoveAt(QueueData.Instance.SelectedIndex);
// We don't have to change the selected index because we should be on the next one as we deleted the one
// we were on.
});
this.Margin = new BorderDouble(0, 0, 10, 0);
this.HAnchor = HAnchor.FitToChildren;
@ -440,14 +447,6 @@ namespace MatterHackers.MatterControl.ActionBar
WizardWindow.Show<SetupWizardTroubleshooting>("TroubleShooting", "Trouble Shooting");
}
private void onDoneWithCurrentPartButton_Click(object sender, EventArgs mouseEvent)
{
PrinterConnectionAndCommunication.Instance.ResetToReadyState();
QueueData.Instance.RemoveAt(QueueData.Instance.SelectedIndex);
// We don't have to change the selected index because we should be on the next one as we deleted the one
// we were on.
}
private void onRemoveButton_Click(object sender, EventArgs mouseEvent)
{
QueueData.Instance.RemoveAt(QueueData.Instance.SelectedIndex);
@ -466,9 +465,33 @@ namespace MatterHackers.MatterControl.ActionBar
}
}
string unsavedChangesCaption = "Unsaved Changes";
string unsavedChangesMessage = "You have unsaved changes to your part. Are you sure you want to start this print?";
private void onStartButton_Click(object sender, EventArgs mouseEvent)
{
UiThread.RunOnIdle(() => PrinterConnectionAndCommunication.Instance.PrintActivePartIfPossible());
UiThread.RunOnIdle(() =>
{
var systemWindow = this.Parents<SystemWindow>().FirstOrDefault();
var view3D = systemWindow.ChildrenRecursive<View3DWidget>().FirstOrDefault();
if (view3D != null
&& view3D.ShouldBeSaved)
{
StyledMessageBox.ShowMessageBox((bool startPrint) =>
{
if (startPrint)
{
PrinterConnectionAndCommunication.Instance.PrintActivePartIfPossible();
}
}, unsavedChangesMessage, unsavedChangesCaption, StyledMessageBox.MessageType.YES_NO, "Start Print", "Cancel");
}
else
{
PrinterConnectionAndCommunication.Instance.PrintActivePartIfPossible();
}
}
);
}
private void onStateChanged(object sender, EventArgs e)

View file

@ -78,7 +78,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
Vector2 probePosition = LevelWizardBase.GetPrintLevelPositionToSample(i);
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.use_g30_for_bed_probe))
if (ActiveSliceSettings.Instance.Helpers.UseZProbe())
{
var stepString = string.Format("{0} {1} {2} {3}:", levelingStrings.stepTextBeg, i + 1, levelingStrings.stepTextEnd, 3);
printLevelWizard.AddPage(new AutoProbeFeedback(printLevelWizard, new Vector3(probePosition, startProbeHeight), string.Format("{0} {1} {2} - {3}", stepString, positionLabel, i + 1, autoCalibrateLabel), probePositions, i, allowLessThanZero));
@ -91,7 +91,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
}
}
printLevelWizard.AddPage(new LastPage3PointInstructions(printLevelWizard, "Done".Localize(), levelingStrings.DoneInstructions, probePositions));
printLevelWizard.AddPage(new LastPagelInstructions(printLevelWizard, "Done".Localize(), levelingStrings.DoneInstructions, probePositions));
}
public static string ApplyLeveling(string lineBeingSent, Vector3 currentDestination, PrinterMachineInstruction.MovementTypes movementMode)

View file

@ -134,7 +134,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
Vector2 probePosition = GetPrintLevelPositionToSample(i, bedRadius);
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.use_g30_for_bed_probe))
if (ActiveSliceSettings.Instance.Helpers.UseZProbe())
{
var stepString = string.Format("{0} {1} {2} {3}:", levelingStrings.stepTextBeg, i + 1, levelingStrings.stepTextEnd, numberOfRadialSamples + 1);
printLevelWizard.AddPage(new AutoProbeFeedback(printLevelWizard, new Vector3(probePosition, startProbeHeight), string.Format("{0} {1} {2} - {3}", stepString, positionLabel, i + 1, autoCalibrateLabel), probePositions, i, allowLessThanZero));
@ -147,7 +147,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
}
}
printLevelWizard.AddPage(new LastPageRadialInstructions(printLevelWizard, "Done".Localize(), levelingStrings.DoneInstructions, probePositions));
printLevelWizard.AddPage(new LastPagelInstructions(printLevelWizard, "Done".Localize(), levelingStrings.DoneInstructions, probePositions));
}
public static RadialLevlingFunctions GetLevelingFunctions(int numberOfRadialSamples, PrintLevelingData levelingData, Vector2 bedCenter)

View file

@ -33,6 +33,7 @@ using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.MeshVisualizer;
using MatterHackers.VectorMath;
using System;
using System.Collections.Generic;
namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
@ -59,8 +60,54 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
this.totalSteps = totalSteps;
}
public static List<Vector2> GetManualPositions(string settingsValue, int requiredCount)
{
// can look like "0,1:100,2:50,101"
if (!string.IsNullOrEmpty(settingsValue))
{
var coordinates = settingsValue.Split(':');
if(coordinates.Length == requiredCount)
{
var result = new List<Vector2>();
foreach(var coordinate in coordinates)
{
var xyData = coordinate.Split(',');
if(xyData.Length != 2)
{
// bad data
return null;
}
Vector2 probePosition = new Vector2();
if (!double.TryParse(xyData[0], out probePosition.x))
{
// error
return null;
}
if (!double.TryParse(xyData[1], out probePosition.y))
{
// error
return null;
}
result.Add(probePosition);
}
if (result.Count == requiredCount)
{
return result;
}
}
}
return null;
}
public static Vector2 GetPrintLevelPositionToSample(int index)
{
var manualPositions = GetManualPositions(ActiveSliceSettings.Instance.GetValue(SettingsKey.leveling_manual_positions), 3);
if(manualPositions != null)
{
return manualPositions[index];
}
Vector2 bedSize = ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.bed_size);
Vector2 printCenter = ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.print_center);
@ -159,6 +206,10 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
printLevelWizardWindow = new LevelWizard13PointRadial(runningState);
break;
case PrintLevelingData.LevelingSystem.Probe3x3Mesh:
printLevelWizardWindow = new LevelWizard3x3Mesh(runningState);
break;
default:
throw new NotImplementedException();
}

View file

@ -0,0 +1,440 @@
/*
Copyright (c) 2014, Lars Brubaker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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.
*/
using MatterHackers.Agg;
using MatterHackers.GCodeVisualizer;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.MeshVisualizer;
using MatterHackers.VectorMath;
using System;
using System.Collections.Generic;
using System.Text;
namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
public class LevelWizard3x3Mesh : LevelWizardMeshBase
{
public LevelWizard3x3Mesh(LevelWizardBase.RuningState runningState)
: base(runningState, 500, 370, 21, 3, 3)
{
}
public static string ApplyLeveling(string lineBeingSent, Vector3 currentDestination, PrinterMachineInstruction.MovementTypes movementMode)
{
var settings = ActiveSliceSettings.Instance;
if (settings?.GetValue<bool>(SettingsKey.print_leveling_enabled) == true
&& (lineBeingSent.StartsWith("G0 ") || lineBeingSent.StartsWith("G1 "))
&& lineBeingSent.Length > 2
&& lineBeingSent[2] == ' ')
{
PrintLevelingData levelingData = ActiveSliceSettings.Instance.Helpers.GetPrintLevelingData();
return GetLevelingFunctions(3, 3, levelingData)
.DoApplyLeveling(lineBeingSent, currentDestination, movementMode);
}
return lineBeingSent;
}
public static List<string> ProcessCommand(string lineBeingSent)
{
int commentIndex = lineBeingSent.IndexOf(';');
if (commentIndex > 0) // there is content in front of the ;
{
lineBeingSent = lineBeingSent.Substring(0, commentIndex).Trim();
}
List<string> lines = new List<string>();
lines.Add(lineBeingSent);
if (lineBeingSent.StartsWith("G28")
|| lineBeingSent.StartsWith("G29"))
{
lines.Add("M114");
}
return lines;
}
public override Vector2 GetPrintLevelPositionToSample(int index)
{
var manualPositions = GetManualPositions(ActiveSliceSettings.Instance.GetValue(SettingsKey.leveling_manual_positions), 9);
if (manualPositions != null)
{
return manualPositions[index];
}
Vector2 bedSize = ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.bed_size);
Vector2 printCenter = ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.print_center);
if (ActiveSliceSettings.Instance.GetValue<BedShape>(SettingsKey.bed_shape) == BedShape.Circular)
{
// reduce the bed size by the ratio of the radius (square root of 2) so that the sample positions will fit on a ciclular bed
bedSize *= 1.0 / Math.Sqrt(2);
}
// we know we are getting 3x3 sample positions they run like this
// 6 7 8 Y max
// 3 4 5
// 0 1 2 Y min
int xIndex = index % 3;
int yIndex = index / 3;
Vector2 samplePosition = new Vector2();
switch (xIndex)
{
case 0:
samplePosition.x = printCenter.x - (bedSize.x / 2) * .8;
break;
case 1:
samplePosition.x = printCenter.x;
break;
case 2:
samplePosition.x = printCenter.x + (bedSize.x / 2) * .8;
break;
default:
throw new IndexOutOfRangeException();
}
switch (yIndex)
{
case 0:
samplePosition.y = printCenter.y - (bedSize.y / 2) * .8;
break;
case 1:
samplePosition.y = printCenter.y;
break;
case 2:
samplePosition.y = printCenter.y + (bedSize.y / 2) * .8;
break;
default:
throw new IndexOutOfRangeException();
}
return samplePosition;
}
}
public abstract class LevelWizardMeshBase : LevelWizardBase
{
private static MeshLevlingFunctions currentLevelingFunctions = null;
private LevelingStrings levelingStrings = new LevelingStrings();
public LevelWizardMeshBase(LevelWizardBase.RuningState runningState, int width, int height, int totalSteps, int gridWidth, int gridHeight)
: base(width, height, totalSteps)
{
string printLevelWizardTitle = "MatterControl";
string printLevelWizardTitleFull = "Print Leveling Wizard".Localize();
Title = string.Format("{0} - {1}", printLevelWizardTitle, printLevelWizardTitleFull);
int probeCount = gridWidth * gridHeight;
List<ProbePosition> probePositions = new List<ProbePosition>(probeCount);
for (int i = 0; i < probeCount; i++)
{
probePositions.Add(new ProbePosition());
}
printLevelWizard = new WizardControl();
AddChild(printLevelWizard);
if (runningState == LevelWizardBase.RuningState.InitialStartupCalibration)
{
string requiredPageInstructions = "{0}\n\n{1}".FormatWith(levelingStrings.requiredPageInstructions1, levelingStrings.requiredPageInstructions2);
printLevelWizard.AddPage(new FirstPageInstructions(levelingStrings.initialPrinterSetupStepText, requiredPageInstructions));
}
printLevelWizard.AddPage(new FirstPageInstructions(levelingStrings.OverviewText, levelingStrings.WelcomeText(probeCount, 5)));
printLevelWizard.AddPage(new HomePrinterPage(levelingStrings.homingPageStepText, levelingStrings.homingPageInstructions));
string positionLabel = "Position".Localize();
string autoCalibrateLabel = "Auto Calibrate".Localize();
string lowPrecisionLabel = "Low Precision".Localize();
string medPrecisionLabel = "Medium Precision".Localize();
string highPrecisionLabel = "High Precision".Localize();
double bedRadius = Math.Min(ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.bed_size).x, ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.bed_size).y) / 2;
bool allowLessThanZero = ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.z_can_be_negative);
double startProbeHeight = ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.print_leveling_probe_start);
for (int i = 0; i < probeCount; i++)
{
Vector2 probePosition = GetPrintLevelPositionToSample(i);
if (ActiveSliceSettings.Instance.Helpers.UseZProbe())
{
var stepString = string.Format("{0} {1} {2} {3}:", levelingStrings.stepTextBeg, i + 1, levelingStrings.stepTextEnd, probeCount);
printLevelWizard.AddPage(new AutoProbeFeedback(printLevelWizard, new Vector3(probePosition, startProbeHeight), string.Format("{0} {1} {2} - {3}", stepString, positionLabel, i + 1, autoCalibrateLabel), probePositions, i, allowLessThanZero));
}
else
{
printLevelWizard.AddPage(new GetCoarseBedHeight(printLevelWizard, new Vector3(probePosition, startProbeHeight), string.Format("{0} {1} {2} - {3}", levelingStrings.GetStepString(totalSteps), positionLabel, i + 1, lowPrecisionLabel), probePositions, i, allowLessThanZero));
printLevelWizard.AddPage(new GetFineBedHeight(printLevelWizard, string.Format("{0} {1} {2} - {3}", levelingStrings.GetStepString(totalSteps), positionLabel, i + 1, medPrecisionLabel), probePositions, i, allowLessThanZero));
printLevelWizard.AddPage(new GetUltraFineBedHeight(printLevelWizard, string.Format("{0} {1} {2} - {3}", levelingStrings.GetStepString(totalSteps), positionLabel, i + 1, highPrecisionLabel), probePositions, i, allowLessThanZero));
}
}
printLevelWizard.AddPage(new LastPagelInstructions(printLevelWizard, "Done".Localize(), levelingStrings.DoneInstructions, probePositions));
}
public static MeshLevlingFunctions GetLevelingFunctions(int gridWidth, int gridHeight, PrintLevelingData levelingData)
{
if (currentLevelingFunctions == null
|| currentLevelingFunctions.LevelingData != levelingData)
{
if (currentLevelingFunctions != null)
{
currentLevelingFunctions.Dispose();
}
currentLevelingFunctions = new MeshLevlingFunctions(gridWidth, gridHeight, levelingData);
}
return currentLevelingFunctions;
}
new public abstract Vector2 GetPrintLevelPositionToSample(int index);
}
public class MeshLevlingFunctions : IDisposable
{
private Vector3 lastDestinationWithLevelingApplied = new Vector3();
private EventHandler unregisterEvents;
public MeshLevlingFunctions(int gridWidth, int gridHeight, PrintLevelingData levelingData)
{
this.LevelingData = levelingData;
PrinterConnectionAndCommunication.Instance.PositionRead.RegisterEvent(PrinterReportedPosition, ref unregisterEvents);
for (int y = 0; y < gridHeight - 1; y++)
{
for (int x = 0; x < gridWidth - 1; x++)
{
// add all the regions
Regions.Add(new Region()
{
LeftBottom = levelingData.SampledPositions[y * gridWidth + x],
RightBottom = levelingData.SampledPositions[y * gridWidth + x + 1],
LeftTop = levelingData.SampledPositions[(y + 1) * gridWidth + x],
RightTop = levelingData.SampledPositions[(y + 1) * gridWidth + x + 1],
});
}
}
}
// you can only set this on construction
public PrintLevelingData LevelingData { get; private set; }
public List<Region> Regions { get; private set; } = new List<Region>();
public void Dispose()
{
unregisterEvents?.Invoke(this, null);
}
public string DoApplyLeveling(string lineBeingSent, Vector3 currentDestination,
PrinterMachineInstruction.MovementTypes movementMode)
{
double extruderDelta = 0;
GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref extruderDelta);
double feedRate = 0;
GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref feedRate);
StringBuilder newLine = new StringBuilder("G1 ");
if (lineBeingSent.Contains("X") || lineBeingSent.Contains("Y") || lineBeingSent.Contains("Z"))
{
Vector3 outPosition = GetPositionWithZOffset(currentDestination);
if (movementMode == PrinterMachineInstruction.MovementTypes.Relative)
{
Vector3 delta = outPosition - lastDestinationWithLevelingApplied;
lastDestinationWithLevelingApplied = outPosition;
outPosition = delta;
}
else
{
lastDestinationWithLevelingApplied = outPosition;
}
newLine = newLine.Append(String.Format("X{0:0.##} Y{1:0.##} Z{2:0.###}", outPosition.x, outPosition.y, outPosition.z));
}
if (extruderDelta != 0)
{
newLine = newLine.Append(String.Format(" E{0:0.###}", extruderDelta));
}
if (feedRate != 0)
{
newLine = newLine.Append(String.Format(" F{0:0.##}", feedRate));
}
lineBeingSent = newLine.ToString();
return lineBeingSent;
}
public Vector3 GetPositionWithZOffset(Vector3 currentDestination)
{
Region region = GetCorrectRegion(currentDestination);
return region.GetPositionWithZOffset(currentDestination);
}
public Vector2 GetPrintLevelPositionToSample(int index, int gridWidth, int gridHeight)
{
var manualPositions = LevelWizardBase.GetManualPositions(ActiveSliceSettings.Instance.GetValue(SettingsKey.leveling_manual_positions), gridWidth * gridHeight);
if (manualPositions != null)
{
return manualPositions[index];
}
Vector2 bedSize = ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.bed_size);
Vector2 printCenter = ActiveSliceSettings.Instance.GetValue<Vector2>(SettingsKey.print_center);
switch (ActiveSliceSettings.Instance.GetValue<BedShape>(SettingsKey.bed_shape))
{
case BedShape.Circular:
Vector2 firstPosition = new Vector2(printCenter.x, printCenter.y + (bedSize.y / 2) * .5);
switch (index)
{
case 0:
return firstPosition;
case 1:
return Vector2.Rotate(firstPosition, MathHelper.Tau / 3);
case 2:
return Vector2.Rotate(firstPosition, MathHelper.Tau * 2 / 3);
default:
throw new IndexOutOfRangeException();
}
case BedShape.Rectangular:
default:
switch (index)
{
case 0:
return new Vector2(printCenter.x, printCenter.y + (bedSize.y / 2) * .8);
case 1:
return new Vector2(printCenter.x - (bedSize.x / 2) * .8, printCenter.y - (bedSize.y / 2) * .8);
case 2:
return new Vector2(printCenter.x + (bedSize.x / 2) * .8, printCenter.y - (bedSize.y / 2) * .8);
default:
throw new IndexOutOfRangeException();
}
}
}
private Region GetCorrectRegion(Vector3 currentDestination)
{
int bestIndex = 0;
double bestDist = double.PositiveInfinity;
currentDestination.z = 0;
for (int regionIndex = 0; regionIndex < Regions.Count; regionIndex++)
{
var dist = (Regions[regionIndex].Center - currentDestination).LengthSquared;
if(dist < bestDist)
{
bestIndex = regionIndex;
bestDist = dist;
}
}
return Regions[bestIndex];
}
private void PrinterReportedPosition(object sender, EventArgs e)
{
lastDestinationWithLevelingApplied = GetPositionWithZOffset(PrinterConnectionAndCommunication.Instance.LastReportedPosition);
}
public class Region
{
public Vector3 LeftBottom { get; set; }
public Vector3 LeftTop { get; set; }
public Vector3 RightBottom { get; set; }
public Vector3 RightTop { get; set; }
internal Vector3 Center { get; private set; }
internal Vector3 LeftBottomCenter { get; private set; }
internal Vector3 RightTopCenter { get; private set; }
internal Plane LeftBottomPlane { get; private set; }
internal Plane RightTopPlane { get; private set; }
internal Vector3 GetPositionWithZOffset(Vector3 currentDestination)
{
if (LeftBottomPlane.PlaneNormal == Vector3.Zero)
{
InitializePlanes();
}
var destinationAtZ0 = new Vector3(currentDestination.x, currentDestination.y, 0);
// which triangle to check (distance to the centers)
if ((LeftBottomCenter - destinationAtZ0).LengthSquared < (RightTopCenter - destinationAtZ0).LengthSquared)
{
double hitDistance = LeftBottomPlane.GetDistanceToIntersection(destinationAtZ0, Vector3.UnitZ);
currentDestination.z += hitDistance;
}
else
{
double hitDistance = RightTopPlane.GetDistanceToIntersection(destinationAtZ0, Vector3.UnitZ);
currentDestination.z += hitDistance;
}
return currentDestination;
}
private void InitializePlanes()
{
LeftBottomPlane = new Plane(LeftBottom, RightBottom, LeftTop);
LeftBottomCenter = (LeftBottom + RightBottom + LeftTop) / 3;
RightTopPlane = new Plane(RightBottom, RightTop, LeftTop);
RightTopCenter = (RightBottom + RightTop + LeftTop) / 3;
Center = (LeftBottomCenter + RightTopCenter) / 2;
}
}
}
}

View file

@ -64,7 +64,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
get
{
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.use_g30_for_bed_probe))
if (ActiveSliceSettings.Instance.Helpers.UseZProbe())
{
return "{0}{1}\n\n{2}{3}".FormatWith(doneLine1, doneLine1b, doneLine3, doneLine3b);
}
@ -79,7 +79,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
get
{
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.use_g30_for_bed_probe))
if (ActiveSliceSettings.Instance.Helpers.UseZProbe())
{
return "{0}\n\n{1}".FormatWith(homingLine1, homingLine3b);
}
@ -99,9 +99,9 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
public string WelcomeText(int numberOfSteps, int numberOfMinutes)
{
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.use_g30_for_bed_probe))
if (ActiveSliceSettings.Instance.Helpers.UseZProbe())
{
numberOfMinutes = 1;
numberOfMinutes = 2;
}
return "{0}\n\n\t• {1}\n\t• {2}\n\t• {3}\n\n{4}\n\n{5}\n\n{6}".FormatWith(

View file

@ -88,12 +88,12 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
}
}
public class LastPageRadialInstructions : InstructionsPage
public class LastPagelInstructions : InstructionsPage
{
protected WizardControl container;
private List<ProbePosition> probePositions;
public LastPageRadialInstructions(WizardControl container, string pageDescription, string instructionsText, List<ProbePosition> probePositions)
public LastPagelInstructions(WizardControl container, string pageDescription, string instructionsText, List<ProbePosition> probePositions)
: base(pageDescription, instructionsText)
{
this.probePositions = probePositions;

View file

@ -19,7 +19,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
};
[JsonConverter(typeof(StringEnumConverter))]
public enum LevelingSystem { Probe3Points, Probe7PointRadial, Probe13PointRadial }
public enum LevelingSystem { Probe3Points, Probe7PointRadial, Probe13PointRadial, Probe3x3Mesh }
public PrintLevelingData(PrinterSettings printerProfile)
{
@ -38,6 +38,9 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
case "13 Point Disk":
return LevelingSystem.Probe13PointRadial;
case "3x3 Mesh":
return LevelingSystem.Probe3x3Mesh;
case "3 Point Plane":
default:
return LevelingSystem.Probe3Points;
@ -143,6 +146,13 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
}
break;
case LevelingSystem.Probe3x3Mesh:
if (SampledPositions.Count != 9) // different criteria for what is not initialized
{
return false;
}
break;
default:
throw new NotImplementedException();
}

View file

@ -19,19 +19,19 @@ namespace MatterHackers.MatterControl
public enum MessageType { OK, YES_NO };
double extraTextScaling = 1;
public static void ShowMessageBox(Action<bool> callback, String message, string caption, MessageType messageType = MessageType.OK, string yesOk = "", string no = "")
public static void ShowMessageBox(Action<bool> callback, String message, string caption, MessageType messageType = MessageType.OK, string yesOk = "", string noCancel = "")
{
ShowMessageBox(callback, message, caption, null, messageType, yesOk, no);
ShowMessageBox(callback, message, caption, null, messageType, yesOk, noCancel);
}
public static void ShowMessageBox(Action<bool> callback, string message, string caption, GuiWidget[] extraWidgetsToAdd, MessageType messageType, string yesOk = "", string no = "")
public static void ShowMessageBox(Action<bool> callback, string message, string caption, GuiWidget[] extraWidgetsToAdd, MessageType messageType, string yesOk = "", string noCancel = "")
{
StyledMessageBox messageBox = new StyledMessageBox(callback, message, caption, messageType, extraWidgetsToAdd, 400, 300, yesOk, no);
StyledMessageBox messageBox = new StyledMessageBox(callback, message, caption, messageType, extraWidgetsToAdd, 400, 300, yesOk, noCancel);
messageBox.CenterInParent = true;
messageBox.ShowAsSystemWindow();
}
public StyledMessageBox(Action<bool> callback, String message, string windowTitle, MessageType messageType, GuiWidget[] extraWidgetsToAdd, double width, double height, string yesOk, string no)
public StyledMessageBox(Action<bool> callback, String message, string windowTitle, MessageType messageType, GuiWidget[] extraWidgetsToAdd, double width, double height, string yesOk, string noCancel)
: base(width, height)
{
if (UserSettings.Instance.IsTouchScreen)
@ -51,9 +51,9 @@ namespace MatterHackers.MatterControl
yesOk = "Yes".Localize();
}
}
if (no == "")
if (noCancel == "")
{
no = "No".Localize();
noCancel = "No".Localize();
}
responseCallback = callback;
@ -134,7 +134,7 @@ namespace MatterHackers.MatterControl
buttonRow.AddChild(new HorizontalSpacer());
Button noButton = textImageButtonFactory.Generate(no, centerText: true);
Button noButton = textImageButtonFactory.Generate(noCancel, centerText: true);
noButton.Name = "No Button";
noButton.Click += noButton_Click;
noButton.Cursor = Cursors.Hand;
@ -145,7 +145,7 @@ namespace MatterHackers.MatterControl
case MessageType.OK:
{
Title = "MatterControl - " + "Alert".Localize();
Button okButton = textImageButtonFactory.Generate("Ok".Localize(), centerText: true);
Button okButton = textImageButtonFactory.Generate(yesOk, centerText: true);
okButton.Name = "Ok Button";
okButton.Cursor = Cursors.Hand;
okButton.Click += okButton_Click;

View file

@ -88,7 +88,7 @@ namespace MatterHackers.MatterControl
textImageButtonFactory.normalTextColor = ActiveTheme.Instance.PrimaryTextColor;
textImageButtonFactory.hoverTextColor = ActiveTheme.Instance.PrimaryTextColor;
textImageButtonFactory.disabledTextColor = new RGBA_Bytes(200, 200, 200);
textImageButtonFactory.disabledTextColor = new RGBA_Bytes(ActiveTheme.Instance.PrimaryTextColor, 100);
textImageButtonFactory.disabledFillColor = new RGBA_Bytes(0, 0, 0, 0);
textImageButtonFactory.pressedTextColor = ActiveTheme.Instance.PrimaryTextColor;

View file

@ -36,7 +36,7 @@ using System.Collections.Generic;
namespace MatterHackers.MatterControl.EeProm
{
public partial class EePromMarlinWindow : SystemWindow
public partial class EePromMarlinWindow : CloseOnDisconnectWindow
{
private EePromMarlinSettings currentEePromSettings;

View file

@ -37,7 +37,33 @@ using System.Collections.Generic;
namespace MatterHackers.MatterControl.EeProm
{
public partial class EePromRepetierWindow : SystemWindow
public class CloseOnDisconnectWindow : SystemWindow
{
private EventHandler unregisterEvents;
public CloseOnDisconnectWindow(double width, double height)
: base(width, height)
{
PrinterConnectionAndCommunication.Instance.CommunicationStateChanged.RegisterEvent((s, e) =>
{
if(!PrinterConnectionAndCommunication.Instance.PrinterIsConnected)
{
this.CloseOnIdle();
}
}, ref unregisterEvents);
}
public override void OnClosed(ClosedEventArgs e)
{
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
}
public class EePromRepetierWindow : CloseOnDisconnectWindow
{
protected TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();

View file

@ -36,6 +36,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -367,7 +368,7 @@ namespace MatterHackers.MatterControl.PrintLibrary.Provider
{
directories = Directory.GetDirectories(Path.Combine(rootPath, currentDirectory));
}
foreach (string directoryName in directories)
foreach (string directoryName in directories.OrderBy(f => f))
{
string subPath = directoryName.Substring(rootPath.Length + 1);
newReadDirectoryDirectories.Add(subPath);
@ -382,7 +383,7 @@ namespace MatterHackers.MatterControl.PrintLibrary.Provider
{
string upperFilter = keywordFilter.ToUpper();
string[] files = Directory.GetFiles(Path.Combine(rootPath, currentDirectory));
foreach (string filename in files)
foreach (string filename in files.OrderBy(f => f))
{
string fileExtensionLower = Path.GetExtension(filename).ToLower();
if (!string.IsNullOrEmpty(fileExtensionLower)
@ -401,7 +402,7 @@ namespace MatterHackers.MatterControl.PrintLibrary.Provider
{
string subDirectory = Path.Combine(rootPath, directory);
string[] subDirectoryFiles = Directory.GetFiles(subDirectory);
foreach (string filename in subDirectoryFiles)
foreach (string filename in subDirectoryFiles.OrderBy(f => f))
{
if (ApplicationSettings.LibraryFilterFileExtensions.Contains(Path.GetExtension(filename).ToLower()))
{

View file

@ -152,6 +152,7 @@
<Compile Include="ConfigurationPage\PrinterSettings\PrinterSettingsView.cs" />
<Compile Include="ConfigurationPage\PrintLeveling\InstructionsPage.cs" />
<Compile Include="ConfigurationPage\PrintLeveling\LevelingStrings.cs" />
<Compile Include="ConfigurationPage\PrintLeveling\LevelWizardMesh.cs" />
<Compile Include="ConfigurationPage\PrintLeveling\LevelWizard7PointRadial.cs" />
<Compile Include="ConfigurationPage\PrintLeveling\LevelWizard13PointRadial.cs" />
<Compile Include="ConfigurationPage\PrintLeveling\LevelWizard3Point.cs" />

View file

@ -88,7 +88,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
AddChild(resetViewButton);
resetViewButton.Click += (sender, e) =>
{
ResetView?.Invoke(this, null);
UiThread.RunOnIdle(() => ResetView?.Invoke(this, null));
};
string translateIconPath = Path.Combine("ViewTransformControls", "translate.png");

View file

@ -28,9 +28,12 @@ either expressed or implied, of the FreeBSD Project.
*/
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.GCodeVisualizer;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.VectorMath;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -44,13 +47,36 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
private object locker = new object();
private PrinterMove moveLocationAtEndOfPauseCode;
private Stopwatch timeSinceLastEndstopRead = new Stopwatch();
bool readOutOfFilament = false;
private EventHandler unregisterEvents;
public PauseHandlingStream(GCodeStream internalStream)
: base(internalStream)
{
PrinterConnectionAndCommunication.Instance.ReadLine.RegisterEvent((s, e) =>
{
StringEventArgs currentEvent = e as StringEventArgs;
if (currentEvent != null)
{
if (currentEvent.Data.Contains("ros_"))
{
if(currentEvent.Data.Contains("TRIGGERED"))
{
readOutOfFilament = true;
}
}
}
}, ref unregisterEvents);
}
public enum PauseReason { UserRequested, PauseLayerReached, GCodeRequest, FillamentRunout }
public override void Dispose()
{
unregisterEvents?.Invoke(this, null);
base.Dispose();
}
public enum PauseReason { UserRequested, PauseLayerReached, GCodeRequest, FilamentRunout }
public PrinterMove LastDestination { get { return lastDestination; } }
@ -63,7 +89,11 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
}
}
public void DoPause(PauseReason pauseReason)
string pauseCaption = "Printer Paused".Localize();
string layerPauseMessage = "Your 3D print has been auto-pasued.\nPause layer{0} reached.".Localize();
string filamentPauseMessage = "Out of filament detected\nYour 3D print has been paused.".Localize();
public void DoPause(PauseReason pauseReason, string layerNumber = "")
{
var pcc = PrinterConnectionAndCommunication.Instance;
switch (pauseReason)
@ -75,10 +105,12 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
case PauseReason.PauseLayerReached:
case PauseReason.GCodeRequest:
pcc.PauseOnLayer.CallEvents(pcc, new PrintItemWrapperEventArgs(pcc.ActivePrintItem));
UiThread.RunOnIdle(() => StyledMessageBox.ShowMessageBox(ResumePrint, layerPauseMessage.FormatWith(layerNumber), pauseCaption, StyledMessageBox.MessageType.YES_NO, "Ok".Localize(), "Resume".Localize()));
break;
case PauseReason.FillamentRunout:
pcc.FillamentRunout.CallEvents(pcc, new PrintItemWrapperEventArgs(pcc.ActivePrintItem));
case PauseReason.FilamentRunout:
pcc.FilamentRunout.CallEvents(pcc, new PrintItemWrapperEventArgs(pcc.ActivePrintItem));
UiThread.RunOnIdle(() => StyledMessageBox.ShowMessageBox(ResumePrint, filamentPauseMessage, pauseCaption, StyledMessageBox.MessageType.YES_NO, "Ok".Localize(), "Resume".Localize()));
break;
}
@ -94,6 +126,15 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
InjectPauseGCode("MH_PAUSE");
}
private void ResumePrint(bool clickedOk)
{
// They clicked either Resume or Ok
if (!clickedOk && PrinterConnectionAndCommunication.Instance.PrinterIsPaused)
{
PrinterConnectionAndCommunication.Instance.Resume();
}
}
public override string ReadLine()
{
string lineToSend = null;
@ -117,8 +158,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
return lineToSend;
}
// We got a line from the gcode we are sending check if we should queue a request for fillament runout
if (ActiveSliceSettings.Instance.GetValue(SettingsKey.fillament_runout_endstop) != "None")
// We got a line from the gcode we are sending check if we should queue a request for filament runout
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.filament_runout_sensor))
{
// request to read the endstop state
if (!timeSinceLastEndstopRead.IsRunning || timeSinceLastEndstopRead.ElapsedMilliseconds > 5000)
@ -139,7 +180,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
string layerNumber = lineToSend.Split(':')[1];
if (PauseOnLayer(layerNumber))
{
DoPause(PauseReason.PauseLayerReached);
DoPause(PauseReason.PauseLayerReached, $" {layerNumber}");
}
}
else if (lineToSend.StartsWith("M226")
@ -148,11 +189,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
DoPause(PauseReason.GCodeRequest);
lineToSend = "";
}
else if (OutOfFillament())
{
DoPause(PauseReason.FillamentRunout);
lineToSend = "";
}
else if (lineToSend == "MH_PAUSE")
{
moveLocationAtEndOfPauseCode = LastDestination;
@ -165,6 +201,12 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
lineToSend = "";
}
else if (readOutOfFilament)
{
readOutOfFilament = false;
DoPause(PauseReason.FilamentRunout);
lineToSend = "";
}
// keep track of the position
if (lineToSend != null
@ -215,15 +257,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
}
}
private bool OutOfFillament()
{
if (ActiveSliceSettings.Instance.GetValue(SettingsKey.fillament_runout_endstop) != "None")
{
}
return false;
}
private bool PauseOnLayer(string layer)
{
int layerNumber;

View file

@ -115,6 +115,10 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
lineBeingSent = LevelWizard13PointRadial.ApplyLeveling(lineBeingSent, currentDestination.position, PrinterMachineInstruction.MovementTypes.Absolute);
break;
case PrintLevelingData.LevelingSystem.Probe3x3Mesh:
lineBeingSent = LevelWizard3x3Mesh.ApplyLeveling(lineBeingSent, currentDestination.position, PrinterMachineInstruction.MovementTypes.Absolute);
break;
default:
throw new NotImplementedException();
}

View file

@ -109,7 +109,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication
public RootedObjectEventHandler PauseOnLayer = new RootedObjectEventHandler();
public RootedObjectEventHandler FillamentRunout = new RootedObjectEventHandler();
public RootedObjectEventHandler FilamentRunout = new RootedObjectEventHandler();
public RootedObjectEventHandler PrintingStateChanged = new RootedObjectEventHandler();
@ -117,7 +117,20 @@ namespace MatterHackers.MatterControl.PrinterCommunication
public RootedObjectEventHandler WroteLine = new RootedObjectEventHandler();
public bool WatingForPositionRead { get { return waitingForPosition.IsRunning || PositionReadQueued; } }
public bool WatingForPositionRead
{
get
{
// make sure the longest we will wait under any circumstance is 60 seconds
if (waitingForPosition.ElapsedMilliseconds > 60000)
{
waitingForPosition.Reset();
PositionReadQueued = false;
}
return waitingForPosition.IsRunning || PositionReadQueued;
}
}
public RootedObjectEventHandler AtxPowerStateChanged = new RootedObjectEventHandler();
@ -304,23 +317,18 @@ namespace MatterHackers.MatterControl.PrinterCommunication
#endregion hardware failure callbacks
WriteLineStartCallBacks.AddCallbackToKey("G90", MovementWasSetToAbsoluteMode);
WriteLineStartCallBacks.AddCallbackToKey("G91", MovementWasSetToRelativeMode);
WriteLineStartCallBacks.AddCallbackToKey("M80", AtxPowerUpWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M81", AtxPowerDownWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M82", ExtruderWasSetToAbsoluteMode);
WriteLineStartCallBacks.AddCallbackToKey("M83", ExtruderWasSetToRelativeMode);
WriteLineStartCallBacks.AddCallbackToKey("M104", ExtruderTemperatureWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M106", FanSpeedWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M107", FanOffWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M109", ExtruderTemperatureWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M140", BedTemperatureWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M190", BedTemperatureWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M106", FanSpeedWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M107", FanOffWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M82", ExtruderWasSetToAbsoluteMode);
WriteLineStartCallBacks.AddCallbackToKey("M83", ExtruderWasSetToRelativeMode);
WriteLineStartCallBacks.AddCallbackToKey("G90", MovementWasSetToAbsoluteMode);
WriteLineStartCallBacks.AddCallbackToKey("G91", MovementWasSetToRelativeMode);
WriteLineStartCallBacks.AddCallbackToKey("M80", AtxPowerUpWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("M81", AtxPowerDownWasWritenToPrinter);
WriteLineStartCallBacks.AddCallbackToKey("T", ExtruderIndexSet);
ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
@ -1419,9 +1427,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication
}
}
if (currentLineIndexToSend >= allCheckSumLinesSent.Count)
if (currentLineIndexToSend >= allCheckSumLinesSent.Count
|| currentLineIndexToSend == 1)
{
SendLineToPrinterNow("M110 N1");
allCheckSumLinesSent.SetStartingIndex(1);
waitingForPosition.Reset();
PositionReadQueued = false;
}
}
}
@ -1624,6 +1636,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication
if (segments.Length <= MAX_INVALID_CONNECTION_CHARS)
{
CommunicationState = CommunicationStates.Connected;
TurnOffBedAndExtruders(); // make sure our ui and the printer agree and that the printer is in a known state (not heating).
haveReportedError = false;
// now send any command that initialize this printer
ClearQueuedGCode();
@ -1734,7 +1747,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication
PositionRead.CallEvents(this, null);
waitingForPosition.Stop();
waitingForPosition.Reset();
PositionReadQueued = false;
}
@ -2816,6 +2828,10 @@ namespace MatterHackers.MatterControl.PrinterCommunication
else
{
lineWithCount = $"N{allCheckSumLinesSent.Count} {lineToWrite}";
if (lineToWrite.StartsWith("M999"))
{
allCheckSumLinesSent.SetStartingIndex(1);
}
}
string lineWithChecksum = lineWithCount + "*" + GCodeFile.CalculateChecksum(lineWithCount).ToString();
@ -2913,8 +2929,10 @@ namespace MatterHackers.MatterControl.PrinterCommunication
AbortConnectionAttempt("Connection Lost - " + ex.Message);
}
}
catch (TimeoutException) // known ok
catch (TimeoutException e2) // known ok
{
// This writes on the next line, and there may have been another write attempt before it is printer. Write indented to attempt to show its association.
PrinterOutputCache.Instance.WriteLine(" Error writing command:" + e2.Message);
}
catch (UnauthorizedAccessException e3)
{

View file

@ -48,7 +48,6 @@ namespace MatterHackers.MatterControl.PrinterControls
{
public class MovementControls : ControlWidgetBase
{
public bool hotKeysEnabled = false;
public FlowLayoutWidget manualControlsLayout;
private Button disableMotors;
private EditManualMovementSpeedsWindow editManualMovementSettingsWindow;
@ -56,7 +55,6 @@ namespace MatterHackers.MatterControl.PrinterControls
private Button homeXButton;
private Button homeYButton;
private Button homeZButton;
private TextImageButtonFactory hotKeyButtonFactory = new TextImageButtonFactory();
internal JogControls jogControls;
private AltGroupBox movementControlsGroupBox;

View file

@ -44,7 +44,6 @@ namespace MatterHackers.MatterControl
{
protected TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
protected TextWidget actualTempIndicator;
protected Button tempOffButton;
protected FlowLayoutWidget presetButtonsContainer;
protected EditableNumberDisplay targetTemperatureDisplay;
@ -107,7 +106,7 @@ namespace MatterHackers.MatterControl
}
}
protected FlowLayoutWidget tempSliderContainer;
protected FlowLayoutWidget tempEditContainer;
private EditTemperaturePresetsWindow editSettingsWindow;
protected void AddChildElements()
@ -139,14 +138,14 @@ namespace MatterHackers.MatterControl
{
// put in the temperature slider and preset buttons
tempSliderContainer = new FlowLayoutWidget(Agg.UI.FlowDirection.TopToBottom);
tempEditContainer = new FlowLayoutWidget(Agg.UI.FlowDirection.TopToBottom);
{
GuiWidget sliderLabels = GetSliderLabels();
tempSliderContainer.HAnchor = HAnchor.ParentLeftRight;
tempSliderContainer.AddChild(sliderLabels);
tempSliderContainer.Visible = false;
tempEditContainer.HAnchor = HAnchor.ParentLeftRight;
tempEditContainer.AddChild(sliderLabels);
tempEditContainer.Visible = false;
}
GuiWidget spacer = new GuiWidget(0, 10);
spacer.HAnchor = Agg.UI.HAnchor.ParentLeftRight;
@ -242,7 +241,7 @@ namespace MatterHackers.MatterControl
UiThread.RunOnIdle(() =>
{
SetTargetTemperature(temp);
tempSliderContainer.Visible = false;
tempEditContainer.Visible = false;
});
};
}
@ -259,7 +258,7 @@ namespace MatterHackers.MatterControl
UiThread.RunOnIdle(() =>
{
SetTargetTemperature(GetPreheatTemperature());
tempSliderContainer.Visible = false;
tempEditContainer.Visible = false;
});
};
}
@ -273,7 +272,7 @@ namespace MatterHackers.MatterControl
targetTemperatureDisplay = new EditableNumberDisplay(textImageButtonFactory, string.Format("{0:0.0}°C", GetTargetTemperature()), string.Format("{0:0.0}°C", 240.2));
targetTemperatureDisplay.EditEnabled += (sender, e) =>
{
tempSliderContainer.Visible = true;
tempEditContainer.Visible = true;
};
targetTemperatureDisplay.EditComplete += (sender, e) =>
@ -339,11 +338,6 @@ namespace MatterHackers.MatterControl
double buttonOffset = -10 * GuiWidget.DeviceScale;
var offPosition = buttonOffset;
tempOffButton = textImageButtonFactory.Generate("Off".Localize());
tempOffButton.OriginRelativeParent = new Vector2(offPosition, 0);
//sliderLabels.AddChild(tempOffButton);
SortedDictionary<double, string> labels = GetTemperaturePresetLabels();
bool firstElement = true;
@ -370,7 +364,7 @@ namespace MatterHackers.MatterControl
tempButton.Click += (sender, e) =>
{
SetTargetTemperature(temp);
tempSliderContainer.Visible = false;
tempEditContainer.Visible = false;
};
}
}
@ -407,12 +401,23 @@ namespace MatterHackers.MatterControl
}
}
protected void onTemperatureSet(Object sender, EventArgs e)
protected void ExtruderTemperatureSet(Object sender, EventArgs e)
{
TemperatureEventArgs tempArgs = e as TemperatureEventArgs;
if (tempArgs != null && tempArgs.Index0Based == extruderIndex0Based)
{
SetTargetTemperature(tempArgs.Temperature);
string displayString = string.Format("{0:0.0}°C", tempArgs.Temperature);
targetTemperatureDisplay.SetDisplayString(displayString);
}
}
protected void BedTemperatureSet(Object sender, EventArgs e)
{
TemperatureEventArgs tempArgs = e as TemperatureEventArgs;
if (tempArgs != null)
{
string displayString = string.Format("{0:0.0}°C", tempArgs.Temperature);
targetTemperatureDisplay.SetDisplayString(displayString);
}
}
}
@ -443,8 +448,7 @@ namespace MatterHackers.MatterControl
private void AddHandlers()
{
PrinterConnectionAndCommunication.Instance.ExtruderTemperatureRead.RegisterEvent(onTemperatureRead, ref unregisterEvents);
PrinterConnectionAndCommunication.Instance.ExtruderTemperatureSet.RegisterEvent(onTemperatureSet, ref unregisterEvents);
tempOffButton.Click += onOffButtonClicked;
PrinterConnectionAndCommunication.Instance.ExtruderTemperatureSet.RegisterEvent(ExtruderTemperatureSet, ref unregisterEvents);
}
public override void OnClosed(ClosedEventArgs e)
@ -453,11 +457,6 @@ namespace MatterHackers.MatterControl
base.OnClosed(e);
}
private void onOffButtonClicked(object sender, EventArgs e)
{
SetTargetTemperature(0);
}
protected override string GetTemperaturePresets()
{
string default_presets = ",0,,0,,0,250";
@ -540,8 +539,7 @@ namespace MatterHackers.MatterControl
private void AddHandlers()
{
PrinterConnectionAndCommunication.Instance.BedTemperatureRead.RegisterEvent(onTemperatureRead, ref unregisterEvents);
PrinterConnectionAndCommunication.Instance.BedTemperatureSet.RegisterEvent(onTemperatureSet, ref unregisterEvents);
tempOffButton.Click += onOffButtonClicked;
PrinterConnectionAndCommunication.Instance.BedTemperatureSet.RegisterEvent(BedTemperatureSet, ref unregisterEvents);
}
public override void OnClosed(ClosedEventArgs e)

View file

@ -239,6 +239,10 @@ namespace MatterHackers.MatterControl
PrinterOutputCache.Instance.PrinterLines.Add(writeFaildeWaring);
PrinterOutputCache.Instance.PrinterLines.Add(cantAccessPath.FormatWith(filePathToSave));
PrinterOutputCache.Instance.PrinterLines.Add("");
UiThread.RunOnIdle(() => {
StyledMessageBox.ShowMessageBox(null, e.Message, "Couldn't save file".Localize());
});
}
}
}

View file

@ -40,6 +40,8 @@ using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrinterControls;
using MatterHackers.MatterControl.SlicerConfiguration;
using System.Linq;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
@ -56,8 +58,7 @@ namespace MatterHackers.MatterControl
private MoveButton zPlusControl;
private MoveButton zMinusControl;
RadioButton hotKeyButton;
private MoveButtonFactory moveButtonFactory = new MoveButtonFactory();
public JogControls(XYZColors colors)
@ -87,88 +88,6 @@ namespace MatterHackers.MatterControl
xYZWithDistance.AddChild(xYZControls);
}
this.KeyDown += (sender, e) =>
{
if (hotKeyButton == null ||
!hotKeyButton.Checked)
{
return;
}
double moveAmountPositive = AxisMoveAmount;
double moveAmountNegative = -AxisMoveAmount;
int eMoveAmountPositive = EAxisMoveAmount;
int eMoveAmountNegative = -EAxisMoveAmount;
if (OsInformation.OperatingSystem == OSType.Windows
|| OsInformation.OperatingSystem == OSType.Mac)
{
if (e.KeyCode == Keys.Z)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.Z);
}
else if (e.KeyCode == Keys.Y)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.Y);
}
else if (e.KeyCode == Keys.X)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.X);
}
else if (e.KeyCode == Keys.Left)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.X, moveAmountNegative, MovementControls.XSpeed);
}
else if (e.KeyCode == Keys.Right)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.X, moveAmountPositive, MovementControls.XSpeed);
}
else if (e.KeyCode == Keys.Up)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Y, moveAmountPositive, MovementControls.YSpeed);
}
else if (e.KeyCode == Keys.Down)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Y, moveAmountNegative, MovementControls.YSpeed);
}
else if (e.KeyCode == Keys.E)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.E, eMoveAmountPositive, MovementControls.EFeedRate(0));
}
else if (e.KeyCode == Keys.R)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.E, eMoveAmountNegative, MovementControls.EFeedRate(0));
}
}
if (OsInformation.OperatingSystem == OSType.Windows)
{
if (e.KeyCode == Keys.Home)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.XYZ);
}
else if (e.KeyCode == Keys.PageUp)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Z, moveAmountPositive, MovementControls.ZSpeed);
}
else if (e.KeyCode == Keys.PageDown)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Z, moveAmountNegative, MovementControls.ZSpeed);
}
}
else if (OsInformation.OperatingSystem == OSType.Mac)
{
if (e.KeyCode == (Keys.Back | Keys.Cancel))
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Z, moveAmountPositive, MovementControls.ZSpeed);
}
else if (e.KeyCode == Keys.Clear)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Z, moveAmountNegative, MovementControls.ZSpeed);
}
}
};
// add in some movement radio buttons
FlowLayoutWidget setMoveDistanceControl = new FlowLayoutWidget();
TextWidget buttonsLabel = new TextWidget("Distance:", textColor: RGBA_Bytes.White);
@ -338,40 +257,153 @@ namespace MatterHackers.MatterControl
private DisableableWidget tooBigForBabyStepping;
private RadioButton movePointZeroTwoMmButton;
private RadioButton moveOneMmButton;
GuiWidget keyboardFocusBorder;
ImageWidget keyboardImage;
private FlowLayoutWidget GetHotkeyControlContainer()
{
TextImageButtonFactory hotKeyButtonFactory = new TextImageButtonFactory();
hotKeyButtonFactory.FixedHeight = 20 * GuiWidget.DeviceScale;
hotKeyButtonFactory.FixedWidth = 30 * GuiWidget.DeviceScale;
hotKeyButtonFactory.fontSize = 8;
FlowLayoutWidget keyFocusedContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
keyFocusedContainer.HAnchor = HAnchor.FitToChildren;
keyFocusedContainer.VAnchor = VAnchor.ParentBottomTop;
keyFocusedContainer.ToolTipText = "Enable cursor keys for movement".Localize();
keyFocusedContainer.Margin = new BorderDouble(left: 10);
hotKeyButtonFactory.checkedBorderColor = ActiveTheme.Instance.PrimaryTextColor;
FlowLayoutWidget hotkeyControlContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
hotkeyControlContainer.HAnchor = HAnchor.FitToChildren;
hotkeyControlContainer.VAnchor = VAnchor.ParentBottomTop;
hotkeyControlContainer.ToolTipText = "Enable cursor keys for movement".Localize();
hotkeyControlContainer.Margin = new BorderDouble(left: 10);
hotKeyButton = hotKeyButtonFactory.GenerateRadioButton("", StaticData.Instance.LoadIcon("hot_key_small_white.png", 19, 12).InvertLightness());
hotKeyButton.Margin = new BorderDouble(5);
hotKeyButton.FocusChanged += (sender, e) =>
var image = StaticData.Instance.LoadIcon("hot_key_small_white.png", 19, 12);
if(ActiveTheme.Instance.IsDarkTheme)
{
if ((sender as GuiWidget).Focused)
image = image.InvertLightness();
}
keyboardImage = new ImageWidget(image)
{
BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor,
VAnchor = VAnchor.ParentCenter,
HAnchor = HAnchor.ParentCenter,
Margin = new BorderDouble(5),
Visible = false,
};
keyboardFocusBorder = new GuiWidget(1, 1)
{
MinimumSize = new Vector2(keyboardImage.Width + 5, keyboardImage.Height + 5),
};
keyboardFocusBorder.AddChild(keyboardImage);
keyFocusedContainer.AddChild(keyboardFocusBorder);
return keyFocusedContainer;
}
// OnLoad overridden for keyboard and only applicable on non-Android builds
#if !__ANDROID__
public override void OnLoad(EventArgs args)
{
var parents = keyboardFocusBorder.Parents<AltGroupBox>();
parents.First().KeyDown += JogControls_KeyDown;
parents.First().ContainsFocusChanged += (sender, e) =>
{
if ((sender as GuiWidget).ContainsFocus
&& !UserSettings.Instance.IsTouchScreen)
{
hotKeyButton.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
keyboardImage.Visible = true;
}
else
{
hotKeyButton.Checked = false;
hotKeyButton.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor;
keyboardImage.Visible = false;
}
};
hotkeyControlContainer.AddChild(hotKeyButton);
base.OnLoad(args);
}
#endif
return hotkeyControlContainer;
private void JogControls_KeyDown(object sender, KeyEventArgs e)
{
double moveAmountPositive = AxisMoveAmount;
double moveAmountNegative = -AxisMoveAmount;
int eMoveAmountPositive = EAxisMoveAmount;
int eMoveAmountNegative = -EAxisMoveAmount;
// if we are not printing and on mac or PC
if (PrinterConnectionAndCommunication.Instance.CommunicationState != PrinterConnectionAndCommunication.CommunicationStates.Printing
&& (OsInformation.OperatingSystem == OSType.Windows || OsInformation.OperatingSystem == OSType.Mac))
{
if (e.KeyCode == Keys.Z)
{
if (PrinterConnectionAndCommunication.Instance.CommunicationState != PrinterConnectionAndCommunication.CommunicationStates.Printing)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.Z);
}
}
else if (e.KeyCode == Keys.Y)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.Y);
}
else if (e.KeyCode == Keys.X)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.X);
}
if (e.KeyCode == Keys.Home)
{
PrinterConnectionAndCommunication.Instance.HomeAxis(PrinterConnectionAndCommunication.Axis.XYZ);
}
else if (e.KeyCode == Keys.Left)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.X, moveAmountNegative, MovementControls.XSpeed);
}
else if (e.KeyCode == Keys.Right)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.X, moveAmountPositive, MovementControls.XSpeed);
}
else if (e.KeyCode == Keys.Up)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Y, moveAmountPositive, MovementControls.YSpeed);
}
else if (e.KeyCode == Keys.Down)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Y, moveAmountNegative, MovementControls.YSpeed);
}
else if (e.KeyCode == Keys.E)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.E, eMoveAmountPositive, MovementControls.EFeedRate(0));
}
else if (e.KeyCode == Keys.R)
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.E, eMoveAmountNegative, MovementControls.EFeedRate(0));
}
}
if ((OsInformation.OperatingSystem == OSType.Windows && e.KeyCode == Keys.PageUp)
|| (OsInformation.OperatingSystem == OSType.Mac && e.KeyCode == (Keys.Back | Keys.Cancel)))
{
if (PrinterConnectionAndCommunication.Instance.CommunicationState == PrinterConnectionAndCommunication.CommunicationStates.Printing)
{
var currentZ = ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.baby_step_z_offset);
currentZ += moveAmountPositive;
ActiveSliceSettings.Instance.SetValue(SettingsKey.baby_step_z_offset, currentZ.ToString("0.##"));
}
else
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Z, moveAmountPositive, MovementControls.ZSpeed);
}
}
else if ((OsInformation.OperatingSystem == OSType.Windows && e.KeyCode == Keys.PageDown)
|| (OsInformation.OperatingSystem == OSType.Mac && e.KeyCode == Keys.Clear))
{
if (PrinterConnectionAndCommunication.Instance.CommunicationState == PrinterConnectionAndCommunication.CommunicationStates.Printing)
{
var currentZ = ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.baby_step_z_offset);
currentZ += moveAmountNegative;
ActiveSliceSettings.Instance.SetValue(SettingsKey.baby_step_z_offset, currentZ.ToString("0.##"));
}
else
{
PrinterConnectionAndCommunication.Instance.MoveRelative(PrinterConnectionAndCommunication.Axis.Z, moveAmountNegative, MovementControls.ZSpeed);
}
}
}
private FlowLayoutWidget CreateEButtons(double buttonSeparationDistance)

View file

@ -41,8 +41,9 @@ namespace MatterHackers.PrinterEmulator
public bool DsrState;
private static Regex numberRegex = new Regex(@"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?");
// no bed present
private Random random = new Random();
private long commandIndex = 1;
private int recievedCount = 0;
// Dictionary of command and response callback
private Dictionary<string, Func<string, string>> responses = new Dictionary<string, Func<string, string>>();
@ -59,11 +60,12 @@ namespace MatterHackers.PrinterEmulator
responses.Add("G4", Wait);
responses.Add("G92", ResetPosition);
responses.Add("M104", SetExtruderTemperature);
responses.Add("M105", RandomTemp);
responses.Add("M105", ReturnTemp);
responses.Add("M106", SetFan);
responses.Add("M109", SetExtruderTemperature);
responses.Add("M110", SetLineCount);
responses.Add("M114", GetPosition);
responses.Add("M115", reportMarlinFirmware);
responses.Add("M115", ReportMarlinFirmware);
responses.Add("M140", SetBedTemperature);
responses.Add("M190", SetBedTemperature);
responses.Add("M20", ListSdCard);
@ -75,24 +77,39 @@ namespace MatterHackers.PrinterEmulator
public event EventHandler FanSpeedChanged;
public double BedCurrentTemperature { get; private set; } = 26;
public double BedGoalTemperature { get; private set; } = -1;
public double EPosition { get; private set; }
public double ExtruderGoalTemperature { get; private set; } = 210;
public double ExtruderCurrentTemperature { get; private set; } = 27;
public double ExtruderGoalTemperature { get; private set; } = 0;
public double FanSpeed { get; private set; }
public string PortName { get; set; }
public bool RunSlow { get; set; }
public bool SimulateLineErrors { get; set; } = false;
public double XPosition { get; private set; }
public double YPosition { get; private set; }
public double ZPosition { get; private set; }
public static int CalculateChecksum(string commandToGetChecksumFor)
{
int checksum = 0;
if (commandToGetChecksumFor.Length > 0)
{
checksum = commandToGetChecksumFor[0];
for (int i = 1; i < commandToGetChecksumFor.Length; i++)
{
checksum ^= commandToGetChecksumFor[i];
}
}
return checksum;
}
public static bool GetFirstNumberAfter(string stringToCheckAfter, string stringWithNumber, ref double readValue, int startIndex = 0)
{
int stringPos = stringWithNumber.IndexOf(stringToCheckAfter, startIndex);
@ -127,7 +144,7 @@ namespace MatterHackers.PrinterEmulator
return command;
}
public string getCommandKey(string command)
public string GetCommandKey(string command)
{
if (command.IndexOf(' ') != -1)
{
@ -136,14 +153,18 @@ namespace MatterHackers.PrinterEmulator
return command;
}
public string GetCorrectResponse(string command)
public string GetCorrectResponse(string inCommand)
{
try
{
// Remove line returns
command = command.Split('\n')[0]; // strip of the trailing cr (\n)
command = ParseChecksumLine(command);
var commandKey = getCommandKey(command);
var commandNoNl = inCommand.Split('\n')[0]; // strip of the trailing cr (\n)
var command = ParseChecksumLine(commandNoNl);
if (command.Contains("Resend"))
{
return command + "ok\n";
}
var commandKey = GetCommandKey(command);
if (responses.ContainsKey(commandKey))
{
if (RunSlow)
@ -169,33 +190,38 @@ namespace MatterHackers.PrinterEmulator
public string GetPosition(string command)
{
// position commands look like this: X:0.00 Y:0.00 Z0.00 E:0.00 Count X: 0.00 Y:0.00 Z:0.00 then an ok on the next line
return $"X:{XPosition:0.00} Y:{YPosition:0.00} Z:{ZPosition:0.00} E:{EPosition:0.00} Count X: 0.00 Y:0.00 Z:0.00\nok\n";
return $"X:{XPosition:0.00} Y: {YPosition:0.00} Z: {ZPosition:0.00} E: {EPosition:0.00} Count X: 0.00 Y: 0.00 Z: 0.00\nok\n";
}
public string ReportMarlinFirmware(string command)
{
return "FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:https://github.com/MarlinFirmware/Marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:Framelis v1 EXTRUDER_COUNT:1 UUID:155f84b5-d4d7-46f4-9432-667e6876f37a\nok\n";
}
// Add response callbacks here
public string RandomTemp(string command)
public string ReturnTemp(string command)
{
// temp commands look like this: ok T:19.4 /0.0 B:0.0 /0.0 @:0 B@:0
if (BedGoalTemperature == -1)
{
return $"ok T:{(ExtruderGoalTemperature + random.Next(-2, 2))}\n";
if (ExtruderGoalTemperature != 0)
{
ExtruderCurrentTemperature = ExtruderCurrentTemperature + (ExtruderGoalTemperature - ExtruderCurrentTemperature) * .8;
}
return $"ok T:{ExtruderCurrentTemperature:0.0} / {ExtruderGoalTemperature:0.0}\n";
}
else
{
return $"ok T:{ExtruderGoalTemperature + random.Next(-2, 2)} B:{BedGoalTemperature + random.Next(-2, 2) }\n";
ExtruderCurrentTemperature = ExtruderCurrentTemperature + (ExtruderGoalTemperature - ExtruderCurrentTemperature) * .8;
BedCurrentTemperature = BedCurrentTemperature + (BedGoalTemperature - BedCurrentTemperature) * .8;
return $"ok T:{ExtruderCurrentTemperature:0.0} / {ExtruderGoalTemperature:0.0} B: {BedCurrentTemperature:0.0} / {BedGoalTemperature:0.0}\n";
}
}
public string reportMarlinFirmware(string command)
{
return "FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:https://github.com/MarlinFirmware/Marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:Framelis v1 EXTRUDER_COUNT:1 UUID:155f84b5-d4d7-46f4-9432-667e6876f37a\nok\n";
}
public string SetFan(string command)
{
try
{
// M104 S210 or M109 S[temp]
var sIndex = command.IndexOf('S') + 1;
FanSpeed = int.Parse(command.Substring(sIndex));
FanSpeedChanged?.Invoke(this, null);
@ -213,6 +239,12 @@ namespace MatterHackers.PrinterEmulator
shutDown = true;
}
public void SimulateRebot()
{
commandIndex = 1;
recievedCount = 0;
}
public void Startup()
{
serialPort = new SerialPort(PortName);
@ -311,11 +343,38 @@ namespace MatterHackers.PrinterEmulator
private string ParseChecksumLine(string command)
{
recievedCount++;
if (SimulateLineErrors && (recievedCount % 11) == 0)
{
command = "N-1 nthoeuc 654*";
}
if (command[0] == 'N')
{
int spaceIndex = command.IndexOf(' ') + 1;
int endIndex = command.IndexOf('*');
return command.Substring(spaceIndex, endIndex - spaceIndex);
double lineNumber = 0;
GetFirstNumberAfter("N", command, ref lineNumber);
var checksumStart = command.LastIndexOf('*');
var commandToChecksum = command.Substring(0, checksumStart);
if(commandToChecksum[commandToChecksum.Length-1] == ' ')
{
commandToChecksum = commandToChecksum.Substring(0, commandToChecksum.Length - 1);
}
double expectedChecksum = 0;
GetFirstNumberAfter("*", command, ref expectedChecksum, checksumStart);
int actualChecksum = CalculateChecksum(commandToChecksum);
if ((lineNumber == commandIndex
&& actualChecksum == expectedChecksum)
|| command.Contains("M110"))
{
commandIndex++;
int spaceIndex = command.IndexOf(' ') + 1;
int endIndex = command.IndexOf('*');
return command.Substring(spaceIndex, endIndex - spaceIndex);
}
else
{
return $"Error:checksum mismatch, Last Line: {commandIndex - 1}\nResend: {commandIndex}\n";
}
}
else
{
@ -361,6 +420,17 @@ namespace MatterHackers.PrinterEmulator
return "ok\n";
}
private string SetLineCount(string command)
{
double number = commandIndex;
if (GetFirstNumberAfter("N", command, ref number))
{
commandIndex = (long)number + 1;
}
return "ok\n";
}
private string SetPosition(string command)
{
double value = 0;

View file

@ -153,7 +153,7 @@ namespace MatterHackers.MatterControl.PrintQueue
{
if (UpdatePartStatus != null)
{
UpdatePartStatus(this, new StringEventArgs("Calculating Total fillament mm..."));
UpdatePartStatus(this, new StringEventArgs("Calculating Total filament mm..."));
}
if (savedGCodeFileNames.Count > 0)

View file

@ -268,6 +268,14 @@ namespace MatterHackers.MatterControl.PrintQueue
private void itemHolder_MouseDownInBounds(object sender, MouseEventArgs mouseEvent)
{
// we can only change the queue selection when we are not printing
if(PrinterConnectionAndCommunication.Instance.PrinterIsPrinting
|| PrinterConnectionAndCommunication.Instance.PrinterIsPaused
|| PrinterConnectionAndCommunication.Instance.CommunicationState == PrinterConnectionAndCommunication.CommunicationStates.PreparingToPrint)
{
return;
}
// Hard-coded processing rule to avoid changing the SelectedIndex when clicks occur
// with the thumbnail region - aka the first 55 pixels
if (!EditMode && mouseEvent.X < 56) return;

View file

@ -34,7 +34,7 @@ using MatterHackers.MatterControl.CustomWidgets;
namespace MatterHackers.MatterControl
{
//Normally step one of the setup process
// Normally step one of the setup process
public class SetupWizardWifi : WizardPage
{
public SetupWizardWifi()
@ -56,20 +56,35 @@ namespace MatterHackers.MatterControl
//Construct buttons
Button skipButton = whiteImageButtonFactory.Generate("Skip".Localize(), centerText: true);
skipButton.Click += (s, e) => this.WizardWindow.ChangeToSetupPrinterForm();
skipButton.Click += (s, e) =>
{
UiThread.RunOnIdle(() =>
{
this.WizardWindow.ChangeToSetupPrinterForm();
});
};
Button nextButton = textImageButtonFactory.Generate("Continue".Localize());
nextButton.Click += (s, e) => this.WizardWindow.ChangeToSetupPrinterForm();
nextButton.Click += (s, e) =>
{
UiThread.RunOnIdle(() =>
{
this.WizardWindow.ChangeToSetupPrinterForm();
});
};
nextButton.Visible = false;
Button configureButton = whiteImageButtonFactory.Generate("Configure".Localize(), centerText: true);
configureButton.Margin = new BorderDouble(0, 0, 10, 0);
configureButton.Click += (s, e) =>
{
nextButton.Visible = true;
skipButton.Visible = false;
configureButton.Visible = false;
MatterControlApplication.Instance.ConfigureWifi();
UiThread.RunOnIdle(() =>
{
nextButton.Visible = true;
skipButton.Visible = false;
configureButton.Visible = false;
MatterControlApplication.Instance.ConfigureWifi();
});
};
connectButtonContainer.AddChild(configureButton);

View file

@ -133,6 +133,62 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
}
}
/// <summary>
/// Order of precidence &, |, !, =
/// </summary>
/// <param name="unsplitSettings"></param>
/// <param name="layerCascade"></param>
/// <returns></returns>
public bool ParseShowString(string unsplitSettings, List<PrinterSettingsLayer> layerCascade)
{
PrinterSettings printerSettings = this;
if (!string.IsNullOrEmpty(unsplitSettings))
{
string[] splitOnAnd = unsplitSettings.Split('&');
foreach (var andGroup in splitOnAnd)
{
bool orResult = false;
string[] splitOnOr = andGroup.Split('|');
foreach (var orGroup in splitOnOr)
{
var matchString = "1";
var orItem = orGroup;
bool negate = orItem.StartsWith("!");
if (negate)
{
orItem = orItem.Substring(1);
}
string sliceSettingValue = "";
if (orItem.Contains("="))
{
string[] splitOnEquals = orItem.Split('=');
sliceSettingValue = printerSettings.GetValue(splitOnEquals[0], layerCascade);
matchString = splitOnEquals[1];
}
else
{
sliceSettingValue = printerSettings.GetValue(orItem, layerCascade);
}
if ((!negate && sliceSettingValue == matchString)
|| (negate && sliceSettingValue != matchString))
{
orResult = true;
}
}
if(orResult == false)
{
return false;
}
}
}
return true;
}
/// <summary>
/// Move conflicting user overrides to the temporary staging area, allowing presets values to take effect
/// </summary>

View file

@ -74,7 +74,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
public const string filament_cost = nameof(filament_cost);
public const string filament_density = nameof(filament_density);
public const string filament_diameter = nameof(filament_diameter);
public const string fillament_runout_endstop = nameof(fillament_runout_endstop);
public const string filament_runout_sensor = nameof(filament_runout_sensor);
public const string fill_density = nameof(fill_density);
public const string fill_thin_gaps = nameof(fill_thin_gaps);
public const string first_layer_extrusion_width = nameof(first_layer_extrusion_width);
@ -93,6 +93,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
public const string layer_height = nameof(layer_height);
public const string layer_name = nameof(layer_name);
public const string layer_to_pause = nameof(layer_to_pause);
public const string leveling_manual_positions = nameof(leveling_manual_positions);
public const string make = nameof(make);
public const string manual_probe_paper_width = nameof(manual_probe_paper_width);
public const string merge_overlapping_lines = nameof(merge_overlapping_lines);
@ -118,7 +119,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
public const string spiral_vase = nameof(spiral_vase);
public const string start_gcode = nameof(start_gcode);
public const string temperature = nameof(temperature);
public const string use_g30_for_bed_probe = nameof(use_g30_for_bed_probe);
public const string use_z_probe = nameof(use_z_probe);
public const string has_z_probe = nameof(has_z_probe);
public const string windows_driver = nameof(windows_driver);
public const string z_can_be_negative = nameof(z_can_be_negative);
public const string z_homes_to_max = nameof(z_homes_to_max);
@ -491,6 +493,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
return ActiveSliceSettings.Instance.GetValue<int>(SettingsKey.extruder_count);
}
public bool UseZProbe()
{
return ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.has_z_probe) && ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.use_z_probe);
}
}
public class PrinterInfo

View file

@ -192,22 +192,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
topCategoryTabs.TabBar.AddChild(new HorizontalSpacer());
topCategoryTabs.TabBar.AddChild(sliceSettingsDetailControl);
if (sliceSettingsDetailControl.SelectedValue == "Advanced" && ActiveSliceSettings.Instance.Helpers.ActiveSliceEngineType() == SlicingEngineTypes.Slic3r)
{
TabPage extraSettingsPage = new TabPage("Other");
SimpleTextTabWidget extraSettingsTextTabWidget = new SimpleTextTabWidget(extraSettingsPage, "Other Tab", 16,
ActiveTheme.Instance.TabLabelSelected, new RGBA_Bytes(), ActiveTheme.Instance.TabLabelUnselected, new RGBA_Bytes());
extraSettingsPage.AnchorAll();
int count;
TabControl extraSettingsSideTabs = CreateExtraSettingsSideTabsAndPages(topCategoryTabs, out count);
if (count > 0)
{
topCategoryTabs.AddTab(extraSettingsTextTabWidget);
sideTabBarsListForLayout.Add(extraSettingsSideTabs.TabBar);
extraSettingsPage.AddChild(extraSettingsSideTabs);
}
}
double sideTabBarsMinimumWidth = 0;
foreach (TabBar tabBar in sideTabBarsListForLayout)
{
@ -519,39 +503,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
return leftSideGroupTabs;
}
public static bool ParseShowString(string unsplitSettings, PrinterSettings printerSettings, List<PrinterSettingsLayer> layerCascade)
{
if (!string.IsNullOrEmpty(unsplitSettings))
{
string[] splitSettings = unsplitSettings.Split('&');
foreach (var inLookupSettings in splitSettings)
{
var lookupSettings = inLookupSettings;
if (!string.IsNullOrEmpty(lookupSettings))
{
string showValue = "0";
if (lookupSettings.StartsWith("!"))
{
showValue = "1";
lookupSettings = lookupSettings.Substring(1);
}
string sliceSettingValue = printerSettings.GetValue(lookupSettings, layerCascade);
if (sliceSettingValue == showValue)
{
return false;
}
}
}
}
return true;
}
private bool CheckIfShouldBeShown(SliceSettingData settingData)
{
bool settingShouldBeShown = ParseShowString(settingData.ShowIfSet, ActiveSliceSettings.Instance, layerCascade);
bool settingShouldBeShown = ActiveSliceSettings.Instance.ParseShowString(settingData.ShowIfSet, layerCascade);
if (viewFilter == NamedSettingsLayers.Material || viewFilter == NamedSettingsLayers.Quality)
{
if (!settingData.ShowAsOverride)

View file

@ -57,9 +57,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
SettingsKey.com_port,
SettingsKey.filament_cost,
SettingsKey.filament_density,
SettingsKey.fillament_runout_endstop,
SettingsKey.filament_runout_sensor,
SettingsKey.leveling_manual_positions,
SettingsKey.manual_probe_paper_width,
SettingsKey.use_g30_for_bed_probe,
SettingsKey.use_z_probe,
SettingsKey.has_z_probe,
SettingsKey.pause_gcode,
SettingsKey.print_leveling_probe_start,
SettingsKey.print_leveling_required_to_print,

View file

@ -132,7 +132,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
new ValuePlusConstant("support_material_interface_extruder", "supportInterfaceExtruder", -1),
new VisibleButNotMappedToEngine("extruder_count"),
new VisibleButNotMappedToEngine("extruders_share_temperature"),
new VisibleButNotMappedToEngine(SettingsKey.baby_step_z_offset),
new VisibleButNotMappedToEngine("g0"),
new VisibleButNotMappedToEngine("solid_shell"),
};

View file

@ -254,41 +254,59 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
if (doMergeInSlicer)
{
int meshCount = meshGroup.Meshes.Count;
for (int meshIndex =0; meshIndex< meshCount; meshIndex++)
if (meshCount > 0)
{
Mesh mesh = meshGroup.Meshes[meshIndex];
if ((meshIndex % 2) == 0)
for (int meshIndex = 0; meshIndex < meshCount; meshIndex++)
{
mergeRules += "({0}".FormatWith(savedStlCount);
}
else
{
if(meshIndex < meshCount -1)
Mesh mesh = meshGroup.Meshes[meshIndex];
if ((meshIndex % 2) == 0)
{
mergeRules += ",({0}".FormatWith(savedStlCount);
mergeRules += "({0}".FormatWith(savedStlCount);
}
else
{
mergeRules += ",{0}".FormatWith(savedStlCount);
if (meshIndex < meshCount - 1)
{
mergeRules += ",({0}".FormatWith(savedStlCount);
}
else
{
mergeRules += ",{0}".FormatWith(savedStlCount);
}
}
int currentMeshMaterialIntdex = MeshMaterialData.Get(mesh).MaterialIndex;
if (materialsToInclude.Contains(currentMeshMaterialIntdex))
{
extruderFilesToSlice.Add(SaveAndGetFilenameForMesh(mesh));
}
savedStlCount++;
}
int currentMeshMaterialIntdex = MeshMaterialData.Get(mesh).MaterialIndex;
if (materialsToInclude.Contains(currentMeshMaterialIntdex))
for (int i = 0; i < meshCount; i++)
{
extruderFilesToSlice.Add(SaveAndGetFilenameForMesh(mesh));
mergeRules += ")";
}
}
else // this extruder has no meshes
{
// check if there are any more meshes after this extruder that will be added
int otherMeshCounts = 0;
for (int otherExtruderIndex = extruderIndex + 1; otherExtruderIndex < extruderMeshGroups.Count; otherExtruderIndex++)
{
otherMeshCounts += extruderMeshGroups[otherExtruderIndex].Meshes.Count;
}
if (otherMeshCounts > 0) // there are more extrudes to use after this not used one
{
// add in a blank for this extruder
mergeRules += $"({savedStlCount})";
}
// save an empty mesh
extruderFilesToSlice.Add(SaveAndGetFilenameForMesh(PlatonicSolids.CreateCube(.001,.001,.001)));
savedStlCount++;
}
for (int i = 0; i < meshCount-1; i++)
{
mergeRules += ")";
}
}
else
{
extruderFilesToSlice.Add(SaveAndGetFilenameForMaterial(meshGroup, materialsToInclude));
}
}
return extruderFilesToSlice.ToArray();
}
return new string[] { "" };

View file

@ -12,6 +12,6 @@
<tr><td id='sendFeedback' class='centeredButton translate'>Send FeedBack</td></tr>
<tr><td>&nbsp;</td></tr>
<tr><td><a href='http://www.matterhackers.com/'>www.matterhackers.com</a></td></tr>
<tr><td><span>Copyright &copy; 2016 MatterHackers, Inc.</span></td></tr>
<tr><td><span>Copyright &copy; 2017 MatterHackers, Inc.</span></td></tr>
<tr><td style='font-size:10pt'><span class='translate'>Build: </span><span class='buildNumber'>Test Build</span><span> | </span><span id='clearCache' class='linkButton translate'>Clear Cache</span></td></tr>
</table>

View file

@ -310,9 +310,10 @@ Advanced
has_heated_bed
has_sd_card_reader
has_power_control
filament_runout_sensor
has_z_probe
enable_network_printing
enable_sailfish_communication
fillament_runout_endstop
Behavior
z_homes_to_max
z_can_be_negative
@ -327,11 +328,12 @@ Advanced
Print Leveling
Machine Settings
print_leveling_solution
leveling_manual_positions
print_leveling_required_to_print
Probe Settings
print_leveling_probe_start
manual_probe_paper_width
use_g30_for_bed_probe
use_z_probe
Print Recovery
Recover Settings
recover_is_enabled

View file

@ -572,6 +572,20 @@
"ReloadUiWhenChanged": true
},
{
"SlicerConfigName": "has_z_probe",
"PresentationName": "Has Z Probe",
"HelpText": "The printer has a z probe for measuring bed level.",
"DataEditType": "HARDWARE_PRESENT",
"ShowAsOverride": true,
"ShowIfSet": null,
"ResetAtEndOfPrint": false,
"DefaultValue": "0",
"ReloadUiWhenChanged": true,
"RebuildGCodeOnChange": false
},
{
"QuickMenuSettings": [ ],
"SetSettingsOnChange": [ ],
"SlicerConfigName": "has_hardware_leveling",
"PresentationName": "Has Hardware Leveling",
"HelpText": "The printer has its own auto bed leveling probe and procedure which can be called using a G29 command during Start G-Code.",
@ -697,7 +711,8 @@
"PresentationName": "Leveling Solution",
"HelpText": "The print leveling algorithm to use.",
"DataEditType": "LIST",
"ExtraSettings": "3 Point Plane,7 Point Disk,13 Point Disk",
"ExtraSettings": "3 Point Plane,7 Point Disk,13 Point Disk,3x3 Mesh",
"ShowAsOverride": true,
"ShowIfSet": "!has_hardware_leveling",
"DefaultValue": "3 Point Plane",
"ReloadUiWhenChanged": true,
@ -706,15 +721,27 @@
{
"QuickMenuSettings": [ ],
"SetSettingsOnChange": [ ],
"SlicerConfigName": "fillament_runout_endstop",
"PresentationName": "Fillament Runout Endstop",
"HelpText": "Specifies the endstop (if any) that is used to detect filament runout. Closed state defines filament has runout. If runout is detected the printers pause G-Code is run.",
"DataEditType": "LIST",
"ExtraSettings": "None,X Min,X Max,Y Min,Y Max,Z Min,Z Max",
"SlicerConfigName": "leveling_manual_positions",
"PresentationName": "Leveling Positions",
"HelpText": "If set, these positions will be used when running the leveling solution. Leave empty for defaults. Data Format:'X1,Y1:...:Xn,Yn'",
"DataEditType": "STRING",
"ExtraSettings": "empty for default",
"ShowAsOverride": true,
"ShowIfSet": "!has_hardware_leveling&print_leveling_solution=3 Point Plane|print_leveling_solution=3x3 Mesh",
"ResetAtEndOfPrint": false,
"DefaultValue": "",
"RebuildGCodeOnChange": false
},
{
"QuickMenuSettings": [ ],
"SetSettingsOnChange": [ ],
"SlicerConfigName": "filament_runout_sensor",
"PresentationName": "Has Filament Runout Sensor",
"HelpText": "Specifies that the firmware has support for ros_0 enstop reporting on M119. TRIGGERED state defines filament has runout. If runout is detected the printers pause G-Code is run.",
"DataEditType": "CHECK_BOX",
"ShowAsOverride": true,
"ResetAtEndOfPrint": false,
"DefaultValue": "None",
"ReloadUiWhenChanged": true,
"DefaultValue": "0",
"RebuildGCodeOnChange": false
},
{
@ -738,12 +765,12 @@
"RebuildGCodeOnChange": false
},
{
"SlicerConfigName": "use_g30_for_bed_probe",
"PresentationName": "Use G30 For Probing",
"SlicerConfigName": "use_z_probe",
"PresentationName": "Use Z Probe",
"HelpText": "Enable this if your printer has hardware support for G30 (automatic bed probing) and you want to use it rather than manually measuring the probe positions.",
"DataEditType": "CHECK_BOX",
"ShowAsOverride": true,
"ShowIfSet": "!has_hardware_leveling",
"ShowIfSet": "!has_hardware_leveling&has_z_probe",
"ResetAtEndOfPrint": false,
"RebuildGCodeOnChange": false,
"DefaultValue": "0"
@ -927,7 +954,10 @@
"PresentationName": "Perimeters",
"HelpText": "Acceleration to use on perimeters. Set to 0 to disable changing the printer's acceleration.",
"DataEditType": "POSITIVE_DOUBLE",
"ExtraSettings": "mm/s<>",
"ExtraSettings": "mm/s",
"ShowAsOverride": true,
"ShowIfSet": null,
"ResetAtEndOfPrint": false,
"DefaultValue": "0"
},
{

View file

@ -6067,3 +6067,42 @@ Translated:Play a sound for notifications
English:Include a picture of my print
Translated:Include a picture of my print
English:If set, these positions will be used when running the 3 point leveling solution. Leave empty for defaults. Data Format:'x1,y1:x2,y2:x3,y3'
Translated:If set, these positions will be used when running the 3 point leveling solution. Leave empty for defaults. Data Format:'x1,y1:x2,y2:x3,y3'
English:Leveling Positions
Translated:Leveling Positions
English:Specifies that the firmware has support for ros_0 enstrop reporting on M119. TRIGGERED state defines filament has runout. If runout is detected the printers pause G-Code is run.
Translated:Specifies that the firmware has support for ros_0 enstrop reporting on M119. TRIGGERED state defines filament has runout. If runout is detected the printers pause G-Code is run.
English:Has Fillament Runout Sensor
Translated:Has Fillament Runout Sensor
English:Specifies that the firmware has support for ros_0 enstop reporting on M119. TRIGGERED state defines filament has runout. If runout is detected the printers pause G-Code is run.
Translated:Specifies that the firmware has support for ros_0 enstop reporting on M119. TRIGGERED state defines filament has runout. If runout is detected the printers pause G-Code is run.
English:If set, these positions will be used when running the leveling solution. Leave empty for defaults. Data Format:'X1,Y1:...:Xn,Yn'
Translated:If set, these positions will be used when running the leveling solution. Leave empty for defaults. Data Format:'X1,Y1:...:Xn,Yn'
English:Printer Paused
Translated:Printer Paused
English:Out of filament detected\nYour 3D print has been paused.
Translated:Out of filament detected\nYour 3D print has been paused.
English:Your 3D print has been auto-pasued.\nPause layer{0} reached.
Translated:Your 3D print has been auto-pasued.\nPause layer{0} reached.
English:Has Filament Runout Sensor
Translated:Has Filament Runout Sensor
English:The printer has a z probe for measuring bed level.
Translated:The printer has a z probe for measuring bed level.
English:Has Z Probe
Translated:Has Z Probe
English:Use Z Probe
Translated:Use Z Probe

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit 4ec505aff081f8ca055fe30b4286838b98f83786
Subproject commit be8a52ece845775cdfb97e621cbb08974c45ad6d

@ -1 +1 @@
Subproject commit 5d0d2a21077067346599bbdde7fb7f03226a7403
Subproject commit e9804e065e6ff1627a824a385c971aab3136ae37

View file

@ -98,8 +98,11 @@ namespace MatterHackers.MatterControl.Tests.Automation
// print a part
testRunner.ClickByName("Start Print Button", 1);
// assert the leveling is working
testRunner.WaitForName("Resume Button", 200);
testRunner.WaitForName("Yes Button", 200);
// close the pause dialog pop-up
testRunner.ClickByName("Yes Button");
Assert.Greater(emulator.ZPosition, 5);
@ -112,6 +115,149 @@ namespace MatterHackers.MatterControl.Tests.Automation
await MatterControlUtilities.RunTest(testToRun, maxTimeToRun: 300);
}
[Test, Apartment(ApartmentState.STA)]
public void ExpectedEmulatorResponses()
{
string[] test1 = new string[]
{
"N1 M110 N1 * 125",
"ok",
"N2 M114 * 37",
"X:0.00 Y: 0.00 Z: 0.00 E: 0.00 Count X: 0.00 Y: 0.00 Z: 0.00",
"ok",
"N3 M105 * 36",
"ok T:27.0 / 0.0",
"N1 M110 N1*125",
"ok",
"N2 M115 * 36",
"FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:https://github.com/MarlinFirmware/Marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:Framelis v1 EXTRUDER_COUNT:1 UUID:155f84b5-d4d7-46f4-9432-667e6876f37a",
"ok",
"N3 M104 T0 S0 * 34",
"ok",
"N4 M104 T1 S0 * 36",
"ok",
"N5 M105 * 34",
"ok T:27.0 / 0.0",
"N6 M105 * 45",
"Error:checksum mismatch, Last Line: 5",
"Resend: 6",
"ok",
"N6 M105 * 33",
"ok T:27.0 / 0.0",
"N7 M105 * 32",
"ok T:27.0 / 0.0",
"N8 M105 * 47",
"ok T:27.0 / 0.0",
"N9 M105 * 46",
"ok T:27.0 / 0.0",
"N10 M105 * 22",
"ok T:27.0 / 0.0",
"N11 M105 * 23",
"ok T:27.0 / 0.0",
"N12 M105 * 20",
"ok T:27.0 / 0.0",
"N13 M105 * 21",
"ok T:27.0 / 0.0",
"N14 M105 * 18",
"ok T:27.0 / 0.0",
"N15 M105 * 19",
"ok T:27.0 / 0.0",
"N16 M105 * 16",
"ok T:27.0 / 0.0",
"N17 M105 * 40",
"Error:checksum mismatch, Last Line: 16",
"Resend: 17",
"ok",
"N17 M105 * 17",
"ok T:27.0 / 0.0",
};
string[] test2 = new string[]
{
"N1 M110 N1*125",
"ok",
"N1 M110 N1*125",
"ok",
"N1 M110 N1*125",
"ok",
"N2 M114*37",
"X:0.00 Y: 0.00 Z: 0.00 E: 0.00 Count X: 0.00 Y: 0.00 Z: 0.00",
"ok",
};
SimulatePrint(test1);
SimulatePrint(test2);
}
private static void SimulatePrint(string[] sendRecieveLog)
{
Emulator emulator = new Emulator();
int lineIndex = 0;
while (lineIndex < sendRecieveLog.Length)
{
var sentCommand = sendRecieveLog[lineIndex];
string response = emulator.GetCorrectResponse(sentCommand);
lineIndex++;
var lines = response.Split('\n');
for (int i = 0; i < lines.Length; i++)
{
if (!string.IsNullOrEmpty(lines[i]))
{
Assert.AreEqual(sendRecieveLog[lineIndex], lines[i]);
lineIndex++;
}
}
}
}
[Test, Apartment(ApartmentState.STA)]
public async Task PrinterRequestsResumeWorkingAsExpected()
{
AutomationTest testToRun = (testRunner) =>
{
testRunner.WaitForName("Cancel Wizard Button", 1);
using (var emulatorDisposable = testRunner.LaunchAndConnectToPrinterEmulator())
{
var emulator = emulatorDisposable as Emulator;
Assert.IsTrue(ProfileManager.Instance.ActiveProfile != null);
MatterControlUtilities.SwitchToAdvancedSettings(testRunner);
testRunner.ClickByName("General Tab", 1);
testRunner.ClickByName("Single Print Tab", 1);
testRunner.ClickByName("Layer(s) To Pause: Edit");
testRunner.Type("2;6");
// switch to controls so we can see the heights
testRunner.ClickByName("Controls Tab");
// print a part
testRunner.ClickByName("Start Print Button", 1);
// turn on line error simulation
emulator.SimulateLineErrors = true;
// close the pause dialog pop-up (resume)
testRunner.ClickByName("No Button", 200);
// simulate board reboot
emulator.SimulateRebot();
// close the pause dialog pop-up (resume)
testRunner.ClickByName("No Button", 200);
// Wait for done
testRunner.WaitForName("Done Button", 60);
testRunner.WaitForName("Print Again Button", 1);
}
return Task.FromResult(0);
};
await MatterControlUtilities.RunTest(testToRun, maxTimeToRun: 300);
}
private EventHandler unregisterEvents;
[Test, Apartment(ApartmentState.STA)]
@ -363,24 +509,19 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.ClickByName("Start Print Button", 1);
testRunner.Delay(5);
int tempChangedCount = 0;
int fanChangedCount = 0;
emulator.ExtruderTemperatureChanged += (s, e) =>
{
tempChangedCount++;
};
emulator.FanSpeedChanged += (s, e) =>
{
fanChangedCount++;
};
testRunner.CloseMatterControlViaMenu();
testRunner.ClickByName("Yes Button");
testRunner.Delay(5);
Assert.AreEqual(1, tempChangedCount, "We should change this while exiting a print.");
Assert.AreEqual(1, fanChangedCount, "We should change this while exiting a print.");
Assert.AreEqual(0, emulator.ExtruderGoalTemperature, "We need to set the temp to 0.");
// TODO: chagne this to checking that the fan speed is 0 - when the emulator tracks fan speed.
Assert.AreEqual(1, fanChangedCount, "We expected to see fan chage on quiting.");
}
return Task.FromResult(0);

View file

@ -134,6 +134,11 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.ClickByName("Start Print Button", 1);
// assert the leveling is working
testRunner.WaitForName("Yes Button", 200);
// close the pause dialog pop-up
testRunner.ClickByName("Yes Button");
testRunner.WaitForName("Resume Button", 30);
testRunner.ClickByName("Cancel Print Button");
@ -160,7 +165,10 @@ namespace MatterHackers.MatterControl.Tests.Automation
private static void WaitForLayerAndResume(AutomationRunner testRunner, int indexToWaitFor)
{
testRunner.WaitForName("Resume Button", 30);
// assert the leveling is working
testRunner.WaitForName("Yes Button", 30);
// close the pause dialog pop-up
testRunner.ClickByName("Yes Button");
SystemWindow containingWindow;
GuiWidget layerNumber = testRunner.GetWidgetByName("Current GCode Layer Edit", out containingWindow, 20);

View file

@ -185,11 +185,107 @@ namespace MatterControl.Tests.MatterControl
Assert.AreEqual(outPosition2.z, levelingData.SampledPositions[6].z, .001);
}
[Test, Category("Leveling")]
public void LevelingMesh3x3CorectInterpolation()
{
StaticData.Instance = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData"));
MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4));
// a 2 x 2 mesh that goes form 0 on the left to 10 on the right
{
var levelingData = new PrintLevelingData(ActiveSliceSettings.Instance);
// put them in left to right - bottom to top
levelingData.SampledPositions = new List<Vector3>();
levelingData.SampledPositions.Add(new Vector3(0, 0, 0));
levelingData.SampledPositions.Add(new Vector3(10, 0, 10));
levelingData.SampledPositions.Add(new Vector3(0, 10, 0));
levelingData.SampledPositions.Add(new Vector3(10, 10, 10));
MeshLevlingFunctions levelingFunctionsMesh2x2 = new MeshLevlingFunctions(2, 2, levelingData);
// check on points
AssertMeshLevelPoint(new Vector3(0, 0, 0), new Vector3(0, 0, 0), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 0, 0), new Vector3(10, 0, 10), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 10, 0), new Vector3(10, 10, 10), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(0, 10, 0), new Vector3(0, 10, 0), levelingFunctionsMesh2x2);
// check raised on ponits
AssertMeshLevelPoint(new Vector3(0, 0, 5), new Vector3(0, 0, 5), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 0, 5), new Vector3(10, 0, 15), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 10, 5), new Vector3(10, 10, 15), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(0, 10, 5), new Vector3(0, 10, 5), levelingFunctionsMesh2x2);
// check between points
AssertMeshLevelPoint(new Vector3(5, 0, 0), new Vector3(5, 0, 5), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(5, 0, 5), new Vector3(5, 0, 10), levelingFunctionsMesh2x2);
// check outside points
AssertMeshLevelPoint(new Vector3(-5, 0, 0), new Vector3(-5, 0, -5), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(-5, 0, 5), new Vector3(-5, 0, 0), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(15, 0, 0), new Vector3(15, 0, 15), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(15, 0, 5), new Vector3(15, 0, 20), levelingFunctionsMesh2x2);
}
// a 3 x 3 mesh that goes form 0 on the left to 10 on the right
{
var levelingData = new PrintLevelingData(ActiveSliceSettings.Instance);
// put them in left to right - bottom to top
levelingData.SampledPositions = new List<Vector3>();
levelingData.SampledPositions.Add(new Vector3(0, 0, 0));
levelingData.SampledPositions.Add(new Vector3(5, 0, 5));
levelingData.SampledPositions.Add(new Vector3(10, 0, 10));
levelingData.SampledPositions.Add(new Vector3(0, 5, 0));
levelingData.SampledPositions.Add(new Vector3(5, 5, 5));
levelingData.SampledPositions.Add(new Vector3(10, 5, 10));
levelingData.SampledPositions.Add(new Vector3(0, 10, 0));
levelingData.SampledPositions.Add(new Vector3(5, 10, 5));
levelingData.SampledPositions.Add(new Vector3(10, 10, 10));
MeshLevlingFunctions levelingFunctionsMesh2x2 = new MeshLevlingFunctions(3, 3, levelingData);
// check on points
AssertMeshLevelPoint(new Vector3(0, 0, 0), new Vector3(0, 0, 0), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 0, 0), new Vector3(10, 0, 10), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 10, 0), new Vector3(10, 10, 10), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(0, 10, 0), new Vector3(0, 10, 0), levelingFunctionsMesh2x2);
// check raised on ponits
AssertMeshLevelPoint(new Vector3(0, 0, 5), new Vector3(0, 0, 5), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 0, 5), new Vector3(10, 0, 15), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(10, 10, 5), new Vector3(10, 10, 15), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(0, 10, 5), new Vector3(0, 10, 5), levelingFunctionsMesh2x2);
// check between points
AssertMeshLevelPoint(new Vector3(5, 0, 0), new Vector3(5, 0, 5), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(5, 0, 5), new Vector3(5, 0, 10), levelingFunctionsMesh2x2);
// check outside points
AssertMeshLevelPoint(new Vector3(-5, 0, 0), new Vector3(-5, 0, -5), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(-5, 0, 5), new Vector3(-5, 0, 0), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(15, 0, 0), new Vector3(15, 0, 15), levelingFunctionsMesh2x2);
AssertMeshLevelPoint(new Vector3(15, 0, 5), new Vector3(15, 0, 20), levelingFunctionsMesh2x2);
}
}
void AssertMeshLevelPoint(Vector3 testUnleveled, Vector3 controlLeveled, MeshLevlingFunctions levelingFunctions)
{
Vector3 testLeveled = levelingFunctions.GetPositionWithZOffset(testUnleveled);
Assert.AreEqual(testLeveled.x, testUnleveled.x, .001, "We don't adjust the x or y on mesh leveling");
Assert.AreEqual(testLeveled.x, controlLeveled.x, .001, "We don't adjust the x or y on mesh leveling");
Assert.AreEqual(testLeveled.y, testUnleveled.y, .001, "We don't adjust the x or y on mesh leveling");
Assert.AreEqual(testLeveled.y, controlLeveled.y, .001, "We don't adjust the x or y on mesh leveling");
Assert.AreEqual(testLeveled.z, controlLeveled.z, .001);
string outPositionString = levelingFunctions.DoApplyLeveling(GetGCodeString(testUnleveled), testUnleveled, PrinterMachineInstruction.MovementTypes.Absolute);
Assert.AreEqual(GetGCodeString(testLeveled), outPositionString);
}
private string GetGCodeString(Vector3 destPosition)
{
return "G1 X{0:0.##} Y{1:0.##} Z{2:0.###}".FormatWith(destPosition.x, destPosition.y, destPosition.z);
}
// TODO: do all the same tests for 13 point leveling.
}
}

View file

@ -12,12 +12,82 @@ using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.Agg.PlatformAbstract;
using MatterHackers.Agg;
using MatterHackers.MatterControl.Tests.Automation;
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling;
using MatterHackers.VectorMath;
namespace MatterControl.Tests.MatterControl
{
[TestFixture, Category("ConfigIni")]
public class SettingsParseTests
{
[Test]
public void Check3PointLevelingPositions()
{
StaticData.Instance = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData"));
MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4));
{
var sample0 = LevelWizardBase.GetPrintLevelPositionToSample(0);
var sample1 = LevelWizardBase.GetPrintLevelPositionToSample(1);
var sample2 = LevelWizardBase.GetPrintLevelPositionToSample(2);
Assert.AreEqual("200,200", ActiveSliceSettings.Instance.GetValue(SettingsKey.bed_size));
Assert.AreEqual("100,100", ActiveSliceSettings.Instance.GetValue(SettingsKey.print_center));
Assert.AreEqual("rectangular", ActiveSliceSettings.Instance.GetValue(SettingsKey.bed_shape));
Assert.AreEqual("", ActiveSliceSettings.Instance.GetValue(SettingsKey.leveling_manual_positions));
Assert.AreEqual(new Vector2(100, 180), sample0);
Assert.AreEqual(new Vector2(20, 20), sample1);
Assert.AreEqual(new Vector2(180, 20), sample2);
}
{
// nothing set
var manualPositions = LevelWizardBase.GetManualPositions("", 3);
Assert.IsNull(manualPositions);
// not enough points
manualPositions = LevelWizardBase.GetManualPositions("0,0:100,50", 3);
Assert.IsNull(manualPositions);
// too many points
manualPositions = LevelWizardBase.GetManualPositions("0,0:100,0:200,200:50,3", 3);
Assert.IsNull(manualPositions);
// bad data
manualPositions = LevelWizardBase.GetManualPositions("0,oe:100,0:200,200", 3);
Assert.IsNull(manualPositions);
// good data
manualPositions = LevelWizardBase.GetManualPositions("0,1:100,2:50,101", 3);
Assert.IsTrue(manualPositions.Count == 3);
Assert.IsTrue(manualPositions[0] == new Vector2(0, 1));
Assert.IsTrue(manualPositions[1] == new Vector2(100, 2));
Assert.IsTrue(manualPositions[2] == new Vector2(50, 101));
// good data
manualPositions = LevelWizardBase.GetManualPositions("0,1:100,2:50,103:0,4:100,5:50,106:0,7:100,8:50,109", 9);
Assert.IsTrue(manualPositions.Count == 9);
Assert.IsTrue(manualPositions[0] == new Vector2(0, 1));
Assert.IsTrue(manualPositions[1] == new Vector2(100, 2));
Assert.IsTrue(manualPositions[2] == new Vector2(50, 103));
Assert.IsTrue(manualPositions[3] == new Vector2(0, 4));
Assert.IsTrue(manualPositions[4] == new Vector2(100, 5));
Assert.IsTrue(manualPositions[5] == new Vector2(50, 106));
Assert.IsTrue(manualPositions[6] == new Vector2(0, 7));
Assert.IsTrue(manualPositions[7] == new Vector2(100, 8));
Assert.IsTrue(manualPositions[8] == new Vector2(50, 109));
}
{
ActiveSliceSettings.Instance.SetValue(SettingsKey.leveling_manual_positions, "1,2:211,3:113,104");
var sample0 = LevelWizardBase.GetPrintLevelPositionToSample(0);
var sample1 = LevelWizardBase.GetPrintLevelPositionToSample(1);
var sample2 = LevelWizardBase.GetPrintLevelPositionToSample(2);
Assert.IsTrue(sample0 == new Vector2(1, 2));
Assert.IsTrue(sample1 == new Vector2(211, 3));
Assert.IsTrue(sample2 == new Vector2(113, 104));
}
}
[Test]
public void CheckIfShouldBeShownParseTests()
{
@ -27,57 +97,73 @@ namespace MatterControl.Tests.MatterControl
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "0" };
var profile = GetProfile(settings);
Assert.IsFalse(SliceSettingsWidget.ParseShowString("has_heated_bed", profile, null));
Assert.IsTrue(SliceSettingsWidget.ParseShowString("!has_heated_bed", profile, null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed", null));
Assert.IsTrue(profile.ParseShowString("!has_heated_bed", null));
}
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "1" };
var profile = GetProfile(settings);
Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed", profile, null));
Assert.IsFalse(SliceSettingsWidget.ParseShowString("!has_heated_bed", profile, null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed", null));
}
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "0", SettingsKey.auto_connect, "0" };
var profile = GetProfile(settings);
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&auto_connect", null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&!auto_connect", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&auto_connect", null));
Assert.IsTrue(profile.ParseShowString("!has_heated_bed&!auto_connect", null));
}
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "0", SettingsKey.auto_connect, "1" };
var profile = GetProfile(settings);
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null));
Assert.IsTrue(SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&auto_connect", null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&!auto_connect", null));
Assert.IsTrue(profile.ParseShowString("!has_heated_bed&auto_connect", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&!auto_connect", null));
}
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "0" };
var profile = GetProfile(settings);
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&auto_connect", null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed&!auto_connect", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&auto_connect", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&!auto_connect", null));
}
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "1" };
var profile = GetProfile(settings);
Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&!auto_connect", profile, null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed&auto_connect", null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&!auto_connect", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&auto_connect", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&!auto_connect", null));
}
{
string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "1", SettingsKey.has_fan, "1" };
var profile = GetProfile(settings);
Assert.IsTrue(SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect&has_fan", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&auto_connect&!has_fan", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("has_heated_bed&!auto_connect&has_fan", profile, null));
Assert.IsTrue(!SliceSettingsWidget.ParseShowString("!has_heated_bed&auto_connect&has_fan", profile, null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed&auto_connect&has_fan", null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed&auto_connect&has_fan|!has_sdcard", null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed&auto_connect&!has_sdcard|has_fan", null));
Assert.IsTrue(profile.ParseShowString("has_heated_bed&auto_connect&has_sdcard|has_fan", null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&auto_connect&!has_fan", null));
Assert.IsFalse(profile.ParseShowString("has_heated_bed&!auto_connect&has_fan", null));
Assert.IsFalse(profile.ParseShowString("!has_heated_bed&auto_connect&has_fan", null));
}
// test list setting value
{
string[] settings = new string[] { SettingsKey.has_hardware_leveling, "0", SettingsKey.print_leveling_solution, "3 Point Plane" };
var profile = GetProfile(settings);
Assert.IsTrue(profile.ParseShowString("!has_hardware_leveling&print_leveling_solution=3 Point Plane", null));
Assert.IsTrue(profile.ParseShowString("!has_hardware_leveling&print_leveling_solution=3 Point Plane|print_leveling_solution=3x3 Mesh", null));
Assert.IsTrue(profile.ParseShowString("!has_hardware_leveling&print_leveling_solution=3x3 Mesh|print_leveling_solution=3 Point Plane", null));
Assert.IsTrue(profile.ParseShowString("!has_hardware_leveling&!print_leveling_solution=7 Point Disk", null));
Assert.IsFalse(profile.ParseShowString("has_hardware_leveling&print_leveling_solution=3 Point Plane", null));
Assert.IsFalse(profile.ParseShowString("!has_hardware_leveling&!print_leveling_solution=3 Point Plane", null));
Assert.IsFalse(profile.ParseShowString("!has_hardware_leveling&print_leveling_solution=7 Point Disk", null));
}
}

View file

@ -31,6 +31,14 @@ namespace MatterHackers.MatterControl
}
}
/// <summary>
/// Immediately push application into offline mode
/// </summary>
public void SetOffline()
{
failedRequestCount = 6;
}
public void WebRequestFailed()
{
failedRequestCount++;