2017-08-11 23:13:19 -07:00
|
|
|
|
/*
|
|
|
|
|
|
Copyright (c) 2017, Lars Brubaker, John Lewin
|
|
|
|
|
|
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 System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
using System.Threading.Tasks;
|
2018-01-05 12:44:57 -08:00
|
|
|
|
using MatterControl.Printing;
|
2017-08-18 18:13:15 -07:00
|
|
|
|
using MatterHackers.Agg.Image;
|
2017-08-20 02:34:39 -07:00
|
|
|
|
using MatterHackers.Agg.Platform;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
using MatterHackers.Agg.UI;
|
2018-02-12 14:52:47 -08:00
|
|
|
|
using MatterHackers.DataConverters3D;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
using MatterHackers.Localizations;
|
|
|
|
|
|
using MatterHackers.MatterControl.PrinterCommunication.Io;
|
2018-02-12 14:52:47 -08:00
|
|
|
|
using MatterHackers.MatterControl.PrintQueue;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
using MatterHackers.MatterControl.SlicerConfiguration;
|
2018-01-17 14:03:56 -08:00
|
|
|
|
using MatterHackers.VectorMath;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
|
|
|
|
|
namespace MatterHackers.MatterControl.Library.Export
|
|
|
|
|
|
{
|
|
|
|
|
|
public class GCodeExport : IExportPlugin
|
|
|
|
|
|
{
|
2017-08-19 09:50:08 -07:00
|
|
|
|
public string ButtonText => "Machine File (G-Code)".Localize();
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
|
|
|
|
|
public string FileExtension => ".gcode";
|
|
|
|
|
|
|
|
|
|
|
|
public string ExtensionFilter => "Export GCode|*.gcode";
|
|
|
|
|
|
|
2017-08-20 02:34:39 -07:00
|
|
|
|
public ImageBuffer Icon { get; } = AggContext.StaticData.LoadIcon(Path.Combine("filetypes", "gcode.png"));
|
2017-08-18 18:13:15 -07:00
|
|
|
|
|
2018-02-12 13:55:31 -08:00
|
|
|
|
public bool EnabledForCurrentPart(ILibraryAssetStream libraryContent)
|
2017-08-11 23:13:19 -07:00
|
|
|
|
{
|
|
|
|
|
|
return !libraryContent.IsProtected;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public GuiWidget GetOptionsPanel()
|
|
|
|
|
|
{
|
|
|
|
|
|
// If print leveling is enabled then add in a check box 'Apply Leveling During Export' and default checked.
|
|
|
|
|
|
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.print_leveling_enabled))
|
|
|
|
|
|
{
|
|
|
|
|
|
var container = new FlowLayoutWidget();
|
|
|
|
|
|
|
|
|
|
|
|
var checkbox = new CheckBox("Apply leveling to G-Code during export".Localize(), ActiveTheme.Instance.PrimaryTextColor, 10)
|
|
|
|
|
|
{
|
|
|
|
|
|
Checked = true,
|
|
|
|
|
|
Cursor = Cursors.Hand,
|
|
|
|
|
|
};
|
|
|
|
|
|
checkbox.CheckedStateChanged += (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
this.ApplyLeveling = checkbox.Checked;
|
|
|
|
|
|
};
|
2017-08-19 09:50:08 -07:00
|
|
|
|
//container.AddChild(checkbox);
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
|
|
|
|
|
return container;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<bool> Generate(IEnumerable<ILibraryItem> libraryItems, string outputPath)
|
|
|
|
|
|
{
|
2018-02-12 14:52:47 -08:00
|
|
|
|
// TODO: Export operations need to resolve printer context interactively
|
|
|
|
|
|
var printer = ApplicationController.Instance.ActivePrinter;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
2018-02-12 14:52:47 -08:00
|
|
|
|
var firstItem = libraryItems.OfType<ILibraryAsset>().FirstOrDefault();
|
|
|
|
|
|
if (firstItem != null)
|
2017-08-11 23:13:19 -07:00
|
|
|
|
{
|
2018-02-12 14:52:47 -08:00
|
|
|
|
IObject3D loadedItem = null;
|
2017-11-16 22:01:24 -08:00
|
|
|
|
|
2018-02-12 14:52:47 -08:00
|
|
|
|
if (firstItem.AssetPath == printer.Bed.EditContext.SourceFilePath)
|
2017-08-11 23:13:19 -07:00
|
|
|
|
{
|
2018-02-12 14:52:47 -08:00
|
|
|
|
// If item is bedplate, save any pending changes before starting the print
|
|
|
|
|
|
await ApplicationController.Instance.Tasks.Execute(printer.Bed.SaveChanges);
|
|
|
|
|
|
loadedItem = printer.Bed.Scene;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
}
|
2018-02-12 14:52:47 -08:00
|
|
|
|
else if (firstItem is ILibraryObject3D object3DItem)
|
2017-08-11 23:13:19 -07:00
|
|
|
|
{
|
2018-02-12 14:52:47 -08:00
|
|
|
|
loadedItem = await object3DItem.CreateContent(null);
|
2017-08-11 23:13:19 -07:00
|
|
|
|
}
|
2018-02-12 14:52:47 -08:00
|
|
|
|
else if (firstItem is ILibraryAssetStream assetStream)
|
2018-02-09 18:11:55 -08:00
|
|
|
|
{
|
2018-02-12 14:52:47 -08:00
|
|
|
|
loadedItem = await assetStream.CreateContent(null);
|
|
|
|
|
|
}
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
2018-02-12 14:52:47 -08:00
|
|
|
|
if (loadedItem != null)
|
2017-12-11 14:15:50 -08:00
|
|
|
|
{
|
2018-02-13 12:40:25 -08:00
|
|
|
|
// Necessary to ensure scene or non-persisted ILibraryObject3D content is on disk before slicing
|
|
|
|
|
|
loadedItem.PersistAssets(null);
|
|
|
|
|
|
|
2018-02-12 14:52:47 -08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
string sourceExtension = $".{firstItem.ContentType}";
|
|
|
|
|
|
string assetPath = loadedItem.SaveToAssets();
|
|
|
|
|
|
|
|
|
|
|
|
string fileHashCode = Path.GetFileNameWithoutExtension(assetPath);
|
|
|
|
|
|
|
|
|
|
|
|
string gcodePath = PrintItemWrapper.GCodePath(fileHashCode);
|
|
|
|
|
|
|
2018-02-13 12:41:15 -08:00
|
|
|
|
if (ApplicationSettings.ValidFileExtensions.IndexOf(sourceExtension, StringComparison.OrdinalIgnoreCase) >= 0
|
2018-02-12 14:52:47 -08:00
|
|
|
|
|| string.Equals(sourceExtension, ".mcx", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Get Bounds
|
|
|
|
|
|
var aabb = loadedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
|
|
|
|
|
|
|
|
|
|
|
// Move to bed center
|
|
|
|
|
|
var bedCenter = printer.Bed.BedCenter;
|
|
|
|
|
|
loadedItem.Matrix *= Matrix4X4.CreateTranslation((double)-aabb.Center.X, (double)-aabb.Center.Y, (double)-aabb.minXYZ.Z) * Matrix4X4.CreateTranslation(bedCenter.X, bedCenter.Y, 0);
|
|
|
|
|
|
loadedItem.Color = loadedItem.Color;
|
|
|
|
|
|
|
|
|
|
|
|
// Slice
|
|
|
|
|
|
await ApplicationController.Instance.Tasks.Execute((reporter, cancellationToken) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
return Slicer.SliceItem(loadedItem, gcodePath, printer, reporter, cancellationToken);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (File.Exists(gcodePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
SaveGCodeToNewLocation(gcodePath, outputPath);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-11 23:13:19 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-12 14:52:47 -08:00
|
|
|
|
return false;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-01-11 08:58:43 -08:00
|
|
|
|
public bool ApplyLeveling { get; set; } = true;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
|
|
|
|
|
private void SaveGCodeToNewLocation(string gcodeFilename, string dest)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2018-01-17 14:03:56 -08:00
|
|
|
|
GCodeFileStream gCodeFileStream = new GCodeFileStream(GCodeFile.Load(gcodeFilename,
|
|
|
|
|
|
new Vector4(),
|
|
|
|
|
|
new Vector4(),
|
|
|
|
|
|
new Vector4(),
|
2018-02-02 09:47:06 -08:00
|
|
|
|
Vector4.One,
|
2018-01-17 14:03:56 -08:00
|
|
|
|
CancellationToken.None));
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
2017-09-03 15:50:43 -07:00
|
|
|
|
var printerSettings = ActiveSliceSettings.Instance;
|
|
|
|
|
|
bool addLevelingStream = printerSettings.GetValue<bool>(SettingsKey.print_leveling_enabled) && this.ApplyLeveling;
|
2017-08-11 23:13:19 -07:00
|
|
|
|
var queueStream = new QueuedCommandsStream(gCodeFileStream);
|
|
|
|
|
|
|
|
|
|
|
|
// this is added to ensure we are rewriting the G0 G1 commands as needed
|
|
|
|
|
|
GCodeStream finalStream = addLevelingStream
|
2017-09-05 10:33:14 -07:00
|
|
|
|
? new ProcessWriteRegexStream(printerSettings, new PrintLevelingStream(printerSettings, queueStream, false), queueStream)
|
|
|
|
|
|
: new ProcessWriteRegexStream(printerSettings, queueStream, queueStream);
|
2017-08-11 23:13:19 -07:00
|
|
|
|
|
|
|
|
|
|
using (StreamWriter file = new StreamWriter(dest))
|
|
|
|
|
|
{
|
|
|
|
|
|
string nextLine = finalStream.ReadLine();
|
|
|
|
|
|
while (nextLine != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (nextLine.Trim().Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
file.WriteLine(nextLine);
|
|
|
|
|
|
}
|
|
|
|
|
|
nextLine = finalStream.ReadLine();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
UiThread.RunOnIdle(() =>
|
|
|
|
|
|
{
|
2017-10-18 19:54:06 -07:00
|
|
|
|
StyledMessageBox.ShowMessageBox(e.Message, "Couldn't save file".Localize());
|
2017-08-11 23:13:19 -07:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|