Extract embedded types to new file
This commit is contained in:
parent
f823eb8eb9
commit
d258b60bb1
7 changed files with 537 additions and 484 deletions
|
|
@ -54,473 +54,14 @@ namespace MatterHackers.MatterControl
|
|||
using CustomWidgets;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.GCodeVisualizer;
|
||||
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MeshVisualizer;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.SerialPortCommunication;
|
||||
using MatterHackers.VectorMath;
|
||||
using SettingsManagement;
|
||||
|
||||
public class BedConfig
|
||||
{
|
||||
public event EventHandler ActiveLayerChanged;
|
||||
|
||||
public event EventHandler LoadedGCodeChanged;
|
||||
|
||||
public View3DConfig RendererOptions { get; } = new View3DConfig();
|
||||
|
||||
public PrintItemWrapper printItem = null;
|
||||
|
||||
public PrinterConfig Printer { get; set; }
|
||||
|
||||
public Mesh PrinterShape { get; private set; }
|
||||
|
||||
public BedConfig(PrinterConfig printer = null, bool loadLastBedplate = false)
|
||||
{
|
||||
this.Printer = printer;
|
||||
|
||||
if (loadLastBedplate)
|
||||
{
|
||||
// Find the last used bed plate mcx
|
||||
var directoryInfo = new DirectoryInfo(ApplicationDataStorage.Instance.PlatingDirectory);
|
||||
var firstFile = directoryInfo.GetFileSystemInfos("*.mcx").OrderByDescending(fl => fl.CreationTime).FirstOrDefault();
|
||||
|
||||
// Set as the current item - should be restored as the Active scene in the MeshViewer
|
||||
if (firstFile != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var loadedItem = new PrintItemWrapper(new PrintItem(firstFile.Name, firstFile.FullName));
|
||||
if (loadedItem != null)
|
||||
{
|
||||
this.printItem = loadedItem;
|
||||
}
|
||||
|
||||
this.Scene.Load(firstFile.FullName);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Clear if not assigned above
|
||||
if (this.printItem == null)
|
||||
{
|
||||
this.ClearPlate();
|
||||
}
|
||||
}
|
||||
|
||||
internal void ClearPlate()
|
||||
{
|
||||
string now = DateTime.Now.ToString("yyyyMMdd-HHmmss");
|
||||
|
||||
string mcxPath = Path.Combine(ApplicationDataStorage.Instance.PlatingDirectory, now + ".mcx");
|
||||
|
||||
this.printItem = new PrintItemWrapper(new PrintItem(now, mcxPath));
|
||||
|
||||
File.WriteAllText(mcxPath, new Object3D().ToJson());
|
||||
|
||||
this.Scene.Load(mcxPath);
|
||||
|
||||
// TODO: Define and fire event and eliminate ActiveView3DWidget - model objects need to be dependency free. For the time being prevent application spin up in ClearPlate due to the call below - if MC isn't loaded, don't notify
|
||||
if (!MatterControlApplication.IsLoading)
|
||||
{
|
||||
ApplicationController.Instance.ActiveView3DWidget?.PartHasBeenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GCodeFile loadedGCode;
|
||||
public GCodeFile LoadedGCode
|
||||
{
|
||||
get => loadedGCode;
|
||||
set
|
||||
{
|
||||
if (loadedGCode != value)
|
||||
{
|
||||
loadedGCode = value;
|
||||
LoadedGCodeChanged?.Invoke(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WorldView World { get; } = new WorldView(0, 0);
|
||||
|
||||
public double BuildHeight { get; internal set; }
|
||||
public Vector3 ViewerVolume { get; internal set; }
|
||||
public Vector2 BedCenter { get; internal set; }
|
||||
public BedShape BedShape { get; internal set; }
|
||||
|
||||
// TODO: Make assignment private, wire up post slicing initialization here
|
||||
public GCodeRenderer GCodeRenderer { get; set; }
|
||||
|
||||
public int ActiveLayerIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
return activeLayerIndex;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (activeLayerIndex != value)
|
||||
{
|
||||
activeLayerIndex = value;
|
||||
|
||||
// Clamp activeLayerIndex to valid range
|
||||
if (this.GCodeRenderer == null || activeLayerIndex < 0)
|
||||
{
|
||||
activeLayerIndex = 0;
|
||||
}
|
||||
else if (activeLayerIndex >= this.LoadedGCode.LayerCount)
|
||||
{
|
||||
activeLayerIndex = this.LoadedGCode.LayerCount - 1;
|
||||
}
|
||||
|
||||
// When the active layer changes we update the selected range accordingly - constrain to applicable values
|
||||
this.RenderInfo.EndLayerIndex = Math.Min(this.LoadedGCode == null ? 0 : this.LoadedGCode.LayerCount - 1, Math.Max(activeLayerIndex, 1));
|
||||
|
||||
ActiveLayerChanged?.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int activeLayerIndex;
|
||||
|
||||
public InteractiveScene Scene { get; } = new InteractiveScene();
|
||||
|
||||
public GCodeRenderInfo RenderInfo { get; set; }
|
||||
|
||||
public string GCodePath
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isGCode = Path.GetExtension(printItem.FileLocation).ToUpper() == ".GCODE";
|
||||
return isGCode ? printItem.FileLocation : printItem.GetGCodePathAndFileName();
|
||||
}
|
||||
}
|
||||
|
||||
BedMeshGenerator bedGenerator;
|
||||
|
||||
private Mesh _bedMesh;
|
||||
public Mesh Mesh
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bedMesh == null)
|
||||
{
|
||||
bedGenerator = new BedMeshGenerator();
|
||||
|
||||
//Construct the thing
|
||||
_bedMesh = bedGenerator.CreatePrintBed(Printer);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string url = Printer.Settings.GetValue("PrinterShapeUrl");
|
||||
string extension = Printer.Settings.GetValue("PrinterShapeExtension");
|
||||
|
||||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(extension))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var stream = ApplicationController.Instance.LoadHttpAsset(url))
|
||||
{
|
||||
var mesh = MeshFileIo.Load(stream, extension, CancellationToken.None).Mesh;
|
||||
|
||||
BspNode bspTree = null;
|
||||
|
||||
// if there is a chached bsp tree load it
|
||||
var meshHashCode = mesh.GetLongHashCode();
|
||||
string cachePath = ApplicationController.CacheablePath("MeshBspData", $"{meshHashCode}.bsp");
|
||||
if (File.Exists(cachePath))
|
||||
{
|
||||
JsonConvert.DeserializeObject<BspNode>(File.ReadAllText(cachePath));
|
||||
}
|
||||
else
|
||||
{
|
||||
// else calculate it
|
||||
bspTree = FaceBspTree.Create(mesh, 20, true);
|
||||
// and save it
|
||||
File.WriteAllText(cachePath, JsonConvert.SerializeObject(bspTree));
|
||||
}
|
||||
|
||||
// set the mesh to use the new tree
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
mesh.FaceBspTree = bspTree;
|
||||
this.PrinterShape = mesh;
|
||||
|
||||
// TODO: Need to send a notification that the mesh changed so the UI can pickup and render
|
||||
});
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
|
||||
return _bedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
private Mesh _buildVolumeMesh;
|
||||
|
||||
public Mesh BuildVolumeMesh
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_buildVolumeMesh == null)
|
||||
{
|
||||
//Construct the thing
|
||||
//_buildVolumeMesh = CreatePrintBed(printer);
|
||||
}
|
||||
|
||||
return _buildVolumeMesh;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Render3DLayerFeatures(DrawEventArgs e)
|
||||
{
|
||||
if (this.RenderInfo != null)
|
||||
{
|
||||
// If needed, update the RenderType flags to match to current user selection
|
||||
if (RendererOptions.IsDirty)
|
||||
{
|
||||
this.RenderInfo.RefreshRenderType();
|
||||
RendererOptions.IsDirty = false;
|
||||
}
|
||||
|
||||
this.GCodeRenderer.Render3D(this.RenderInfo, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadGCode(string filePath, CancellationToken cancellationToken, Action<double, string> progressReporter)
|
||||
{
|
||||
this.LoadedGCode = GCodeMemoryFile.Load(filePath, cancellationToken, progressReporter);
|
||||
this.GCodeRenderer = new GCodeRenderer(loadedGCode);
|
||||
|
||||
if (ActiveSliceSettings.Instance.PrinterSelected)
|
||||
{
|
||||
GCodeRenderer.ExtruderWidth = ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.nozzle_diameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
GCodeRenderer.ExtruderWidth = .4;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: After loading we reprocess the entire document just to compute filament used. If it's a feature we need, seems like it should just be normal step during load and result stored in a property
|
||||
GCodeRenderer.GCodeFileToDraw?.GetFilamentUsedMm(ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.filament_diameter));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Print(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecreateBed()
|
||||
{
|
||||
if (bedGenerator != null)
|
||||
{
|
||||
_bedMesh = bedGenerator.CreatePrintBed(Printer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PrinterViewState
|
||||
{
|
||||
public bool SliceSettingsTabPinned
|
||||
{
|
||||
get => UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabPinned) == "true";
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabPinned, value ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
public int SliceSettingsTabIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
int.TryParse(UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabIndex), out int tabIndex);
|
||||
return tabIndex;
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabIndex, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public double SliceSettingsWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
double.TryParse(UserSettings.Instance.get(UserSettingsKey.SliceSettingsWidth), out double controlWidth);
|
||||
return controlWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set(UserSettingsKey.SliceSettingsWidth, value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PrinterConfig
|
||||
{
|
||||
public BedConfig Bed { get; }
|
||||
public PrinterViewState ViewState { get; } = new PrinterViewState();
|
||||
public PrinterSettings Settings { get; private set; } = ActiveSliceSettings.Instance;
|
||||
public PrinterConnection Connection { get; private set; } = PrinterConnection.Instance;
|
||||
|
||||
private EventHandler unregisterEvents;
|
||||
|
||||
public PrinterConfig(bool loadLastBedplate)
|
||||
{
|
||||
this.Bed = new BedConfig(this, loadLastBedplate);
|
||||
|
||||
ActiveSliceSettings.SettingChanged.RegisterEvent(Printer_SettingChanged, ref unregisterEvents);
|
||||
|
||||
// TODO: Needed?
|
||||
//ApplicationController.Instance.AdvancedControlsPanelReloading.RegisterEvent(CheckSettingChanged, ref unregisterEvents);
|
||||
|
||||
ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
|
||||
{
|
||||
this.Settings = ActiveSliceSettings.Instance;
|
||||
this.ReloadSettings();
|
||||
this.Bed.RecreateBed();
|
||||
}, ref unregisterEvents);
|
||||
}
|
||||
|
||||
private void ReloadSettings()
|
||||
{
|
||||
this.Bed.BuildHeight = this.Settings.GetValue<double>(SettingsKey.build_height);
|
||||
this.Bed.ViewerVolume = new Vector3(this.Settings.GetValue<Vector2>(SettingsKey.bed_size), this.Bed.BuildHeight);
|
||||
this.Bed.BedCenter = this.Settings.GetValue<Vector2>(SettingsKey.print_center);
|
||||
this.Bed.BedShape = this.Settings.GetValue<BedShape>(SettingsKey.bed_shape);
|
||||
}
|
||||
|
||||
private void Printer_SettingChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (e is StringEventArgs stringEvent)
|
||||
{
|
||||
if (stringEvent.Data == SettingsKey.bed_size
|
||||
|| stringEvent.Data == SettingsKey.print_center
|
||||
|| stringEvent.Data == SettingsKey.build_height
|
||||
|| stringEvent.Data == SettingsKey.bed_shape)
|
||||
{
|
||||
this.ReloadSettings();
|
||||
this.Bed.RecreateBed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class View3DConfig
|
||||
{
|
||||
public bool IsDirty { get; internal set; }
|
||||
|
||||
public bool RenderGrid
|
||||
{
|
||||
get
|
||||
{
|
||||
string value = UserSettings.Instance.get("GcodeViewerRenderGrid");
|
||||
if (value == null)
|
||||
{
|
||||
RenderGrid = true;
|
||||
return true;
|
||||
}
|
||||
return (value == "True");
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderGrid", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RenderMoves
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerRenderMoves") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderMoves", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RenderRetractions
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerRenderRetractions") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderRetractions", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RenderSpeeds
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerRenderSpeeds") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderSpeeds", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SimulateExtrusion
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerSimulateExtrusion") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerSimulateExtrusion", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TransparentExtrusion
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerTransparentExtrusion") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerTransparentExtrusion", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HideExtruderOffsets
|
||||
{
|
||||
get
|
||||
{
|
||||
string value = UserSettings.Instance.get("GcodeViewerHideExtruderOffsets");
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return (value == "True");
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerHideExtruderOffsets", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SyncToPrint
|
||||
{
|
||||
get => UserSettings.Instance.get("LayerViewSyncToPrint") == "True";
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("LayerViewSyncToPrint", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationController
|
||||
{
|
||||
public ThemeConfig Theme { get; set; } = new ThemeConfig();
|
||||
|
|
|
|||
508
ApplicationView/PrinterModels.cs
Normal file
508
ApplicationView/PrinterModels.cs
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
/*
|
||||
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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
using System.Threading;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.GCodeVisualizer;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MeshVisualizer;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
public class BedConfig
|
||||
{
|
||||
public event EventHandler ActiveLayerChanged;
|
||||
|
||||
public event EventHandler LoadedGCodeChanged;
|
||||
|
||||
public View3DConfig RendererOptions { get; } = new View3DConfig();
|
||||
|
||||
public PrintItemWrapper printItem = null;
|
||||
|
||||
public PrinterConfig Printer { get; set; }
|
||||
|
||||
public Mesh PrinterShape { get; private set; }
|
||||
|
||||
public BedConfig(PrinterConfig printer = null, bool loadLastBedplate = false)
|
||||
{
|
||||
this.Printer = printer;
|
||||
|
||||
if (loadLastBedplate)
|
||||
{
|
||||
// Find the last used bed plate mcx
|
||||
var directoryInfo = new DirectoryInfo(ApplicationDataStorage.Instance.PlatingDirectory);
|
||||
var firstFile = directoryInfo.GetFileSystemInfos("*.mcx").OrderByDescending(fl => fl.CreationTime).FirstOrDefault();
|
||||
|
||||
// Set as the current item - should be restored as the Active scene in the MeshViewer
|
||||
if (firstFile != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var loadedItem = new PrintItemWrapper(new PrintItem(firstFile.Name, firstFile.FullName));
|
||||
if (loadedItem != null)
|
||||
{
|
||||
this.printItem = loadedItem;
|
||||
}
|
||||
|
||||
this.Scene.Load(firstFile.FullName);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Clear if not assigned above
|
||||
if (this.printItem == null)
|
||||
{
|
||||
this.ClearPlate();
|
||||
}
|
||||
}
|
||||
|
||||
internal void ClearPlate()
|
||||
{
|
||||
string now = DateTime.Now.ToString("yyyyMMdd-HHmmss");
|
||||
|
||||
string mcxPath = Path.Combine(ApplicationDataStorage.Instance.PlatingDirectory, now + ".mcx");
|
||||
|
||||
this.printItem = new PrintItemWrapper(new PrintItem(now, mcxPath));
|
||||
|
||||
File.WriteAllText(mcxPath, new Object3D().ToJson());
|
||||
|
||||
this.Scene.Load(mcxPath);
|
||||
|
||||
// TODO: Define and fire event and eliminate ActiveView3DWidget - model objects need to be dependency free. For the time being prevent application spin up in ClearPlate due to the call below - if MC isn't loaded, don't notify
|
||||
if (!MatterControlApplication.IsLoading)
|
||||
{
|
||||
ApplicationController.Instance.ActiveView3DWidget?.PartHasBeenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private GCodeFile loadedGCode;
|
||||
public GCodeFile LoadedGCode
|
||||
{
|
||||
get => loadedGCode;
|
||||
set
|
||||
{
|
||||
if (loadedGCode != value)
|
||||
{
|
||||
loadedGCode = value;
|
||||
LoadedGCodeChanged?.Invoke(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WorldView World { get; } = new WorldView(0, 0);
|
||||
|
||||
public double BuildHeight { get; internal set; }
|
||||
public Vector3 ViewerVolume { get; internal set; }
|
||||
public Vector2 BedCenter { get; internal set; }
|
||||
public BedShape BedShape { get; internal set; }
|
||||
|
||||
// TODO: Make assignment private, wire up post slicing initialization here
|
||||
public GCodeRenderer GCodeRenderer { get; set; }
|
||||
|
||||
public int ActiveLayerIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
return activeLayerIndex;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (activeLayerIndex != value)
|
||||
{
|
||||
activeLayerIndex = value;
|
||||
|
||||
// Clamp activeLayerIndex to valid range
|
||||
if (this.GCodeRenderer == null || activeLayerIndex < 0)
|
||||
{
|
||||
activeLayerIndex = 0;
|
||||
}
|
||||
else if (activeLayerIndex >= this.LoadedGCode.LayerCount)
|
||||
{
|
||||
activeLayerIndex = this.LoadedGCode.LayerCount - 1;
|
||||
}
|
||||
|
||||
// When the active layer changes we update the selected range accordingly - constrain to applicable values
|
||||
this.RenderInfo.EndLayerIndex = Math.Min(this.LoadedGCode == null ? 0 : this.LoadedGCode.LayerCount - 1, Math.Max(activeLayerIndex, 1));
|
||||
|
||||
ActiveLayerChanged?.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int activeLayerIndex;
|
||||
|
||||
public InteractiveScene Scene { get; } = new InteractiveScene();
|
||||
|
||||
public GCodeRenderInfo RenderInfo { get; set; }
|
||||
|
||||
public string GCodePath
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isGCode = Path.GetExtension(printItem.FileLocation).ToUpper() == ".GCODE";
|
||||
return isGCode ? printItem.FileLocation : printItem.GetGCodePathAndFileName();
|
||||
}
|
||||
}
|
||||
|
||||
BedMeshGenerator bedGenerator;
|
||||
|
||||
private Mesh _bedMesh;
|
||||
public Mesh Mesh
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bedMesh == null)
|
||||
{
|
||||
bedGenerator = new BedMeshGenerator();
|
||||
|
||||
//Construct the thing
|
||||
_bedMesh = bedGenerator.CreatePrintBed(Printer);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string url = Printer.Settings.GetValue("PrinterShapeUrl");
|
||||
string extension = Printer.Settings.GetValue("PrinterShapeExtension");
|
||||
|
||||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(extension))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var stream = ApplicationController.Instance.LoadHttpAsset(url))
|
||||
{
|
||||
var mesh = MeshFileIo.Load(stream, extension, CancellationToken.None).Mesh;
|
||||
|
||||
BspNode bspTree = null;
|
||||
|
||||
// if there is a chached bsp tree load it
|
||||
var meshHashCode = mesh.GetLongHashCode();
|
||||
string cachePath = ApplicationController.CacheablePath("MeshBspData", $"{meshHashCode}.bsp");
|
||||
if (File.Exists(cachePath))
|
||||
{
|
||||
JsonConvert.DeserializeObject<BspNode>(File.ReadAllText(cachePath));
|
||||
}
|
||||
else
|
||||
{
|
||||
// else calculate it
|
||||
bspTree = FaceBspTree.Create(mesh, 20, true);
|
||||
// and save it
|
||||
File.WriteAllText(cachePath, JsonConvert.SerializeObject(bspTree));
|
||||
}
|
||||
|
||||
// set the mesh to use the new tree
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
mesh.FaceBspTree = bspTree;
|
||||
this.PrinterShape = mesh;
|
||||
|
||||
// TODO: Need to send a notification that the mesh changed so the UI can pickup and render
|
||||
});
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
|
||||
return _bedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
private Mesh _buildVolumeMesh;
|
||||
|
||||
public Mesh BuildVolumeMesh
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_buildVolumeMesh == null)
|
||||
{
|
||||
//Construct the thing
|
||||
//_buildVolumeMesh = CreatePrintBed(printer);
|
||||
}
|
||||
|
||||
return _buildVolumeMesh;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Render3DLayerFeatures(DrawEventArgs e)
|
||||
{
|
||||
if (this.RenderInfo != null)
|
||||
{
|
||||
// If needed, update the RenderType flags to match to current user selection
|
||||
if (RendererOptions.IsDirty)
|
||||
{
|
||||
this.RenderInfo.RefreshRenderType();
|
||||
RendererOptions.IsDirty = false;
|
||||
}
|
||||
|
||||
this.GCodeRenderer.Render3D(this.RenderInfo, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadGCode(string filePath, CancellationToken cancellationToken, Action<double, string> progressReporter)
|
||||
{
|
||||
this.LoadedGCode = GCodeMemoryFile.Load(filePath, cancellationToken, progressReporter);
|
||||
this.GCodeRenderer = new GCodeRenderer(loadedGCode);
|
||||
|
||||
if (ActiveSliceSettings.Instance.PrinterSelected)
|
||||
{
|
||||
GCodeRenderer.ExtruderWidth = ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.nozzle_diameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
GCodeRenderer.ExtruderWidth = .4;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: After loading we reprocess the entire document just to compute filament used. If it's a feature we need, seems like it should just be normal step during load and result stored in a property
|
||||
GCodeRenderer.GCodeFileToDraw?.GetFilamentUsedMm(ActiveSliceSettings.Instance.GetValue<double>(SettingsKey.filament_diameter));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Print(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecreateBed()
|
||||
{
|
||||
if (bedGenerator != null)
|
||||
{
|
||||
_bedMesh = bedGenerator.CreatePrintBed(Printer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PrinterViewState
|
||||
{
|
||||
public bool SliceSettingsTabPinned
|
||||
{
|
||||
get => UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabPinned) == "true";
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabPinned, value ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
public int SliceSettingsTabIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
int.TryParse(UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabIndex), out int tabIndex);
|
||||
return tabIndex;
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabIndex, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public double SliceSettingsWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
double.TryParse(UserSettings.Instance.get(UserSettingsKey.SliceSettingsWidth), out double controlWidth);
|
||||
return controlWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set(UserSettingsKey.SliceSettingsWidth, value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PrinterConfig
|
||||
{
|
||||
public BedConfig Bed { get; }
|
||||
public PrinterViewState ViewState { get; } = new PrinterViewState();
|
||||
public PrinterSettings Settings { get; private set; } = ActiveSliceSettings.Instance;
|
||||
public PrinterConnection Connection { get; private set; } = PrinterConnection.Instance;
|
||||
|
||||
private EventHandler unregisterEvents;
|
||||
|
||||
public PrinterConfig(bool loadLastBedplate)
|
||||
{
|
||||
this.Bed = new BedConfig(this, loadLastBedplate);
|
||||
|
||||
ActiveSliceSettings.SettingChanged.RegisterEvent(Printer_SettingChanged, ref unregisterEvents);
|
||||
|
||||
// TODO: Needed?
|
||||
//ApplicationController.Instance.AdvancedControlsPanelReloading.RegisterEvent(CheckSettingChanged, ref unregisterEvents);
|
||||
|
||||
ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
|
||||
{
|
||||
this.Settings = ActiveSliceSettings.Instance;
|
||||
this.ReloadSettings();
|
||||
this.Bed.RecreateBed();
|
||||
}, ref unregisterEvents);
|
||||
}
|
||||
|
||||
private void ReloadSettings()
|
||||
{
|
||||
this.Bed.BuildHeight = this.Settings.GetValue<double>(SettingsKey.build_height);
|
||||
this.Bed.ViewerVolume = new Vector3(this.Settings.GetValue<Vector2>(SettingsKey.bed_size), this.Bed.BuildHeight);
|
||||
this.Bed.BedCenter = this.Settings.GetValue<Vector2>(SettingsKey.print_center);
|
||||
this.Bed.BedShape = this.Settings.GetValue<BedShape>(SettingsKey.bed_shape);
|
||||
}
|
||||
|
||||
private void Printer_SettingChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (e is StringEventArgs stringEvent)
|
||||
{
|
||||
if (stringEvent.Data == SettingsKey.bed_size
|
||||
|| stringEvent.Data == SettingsKey.print_center
|
||||
|| stringEvent.Data == SettingsKey.build_height
|
||||
|| stringEvent.Data == SettingsKey.bed_shape)
|
||||
{
|
||||
this.ReloadSettings();
|
||||
this.Bed.RecreateBed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class View3DConfig
|
||||
{
|
||||
public bool IsDirty { get; internal set; }
|
||||
|
||||
public bool RenderGrid
|
||||
{
|
||||
get
|
||||
{
|
||||
string value = UserSettings.Instance.get("GcodeViewerRenderGrid");
|
||||
if (value == null)
|
||||
{
|
||||
RenderGrid = true;
|
||||
return true;
|
||||
}
|
||||
return (value == "True");
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderGrid", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RenderMoves
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerRenderMoves") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderMoves", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RenderRetractions
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerRenderRetractions") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderRetractions", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool RenderSpeeds
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerRenderSpeeds") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerRenderSpeeds", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SimulateExtrusion
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerSimulateExtrusion") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerSimulateExtrusion", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TransparentExtrusion
|
||||
{
|
||||
get { return (UserSettings.Instance.get("GcodeViewerTransparentExtrusion") == "True"); }
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerTransparentExtrusion", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HideExtruderOffsets
|
||||
{
|
||||
get
|
||||
{
|
||||
string value = UserSettings.Instance.get("GcodeViewerHideExtruderOffsets");
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return (value == "True");
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("GcodeViewerHideExtruderOffsets", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SyncToPrint
|
||||
{
|
||||
get => UserSettings.Instance.get("LayerViewSyncToPrint") == "True";
|
||||
set
|
||||
{
|
||||
UserSettings.Instance.set("LayerViewSyncToPrint", value.ToString());
|
||||
this.IsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ using MatterHackers.ImageProcessing;
|
|||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrinterControls;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.VectorMath;
|
||||
using static MatterHackers.MatterControl.JogControls;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ using MatterHackers.DataConverters3D;
|
|||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.PolygonMesh.Processors;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@
|
|||
<Compile Include="ActionBar\TemperatureWidgetBase.cs" />
|
||||
<Compile Include="ActionBar\TemperatureWidgetExtruder.cs" />
|
||||
<Compile Include="ApplicationView\ApplicationController.cs" />
|
||||
<Compile Include="ApplicationView\PrinterModels.cs" />
|
||||
<Compile Include="ApplicationView\ThemeConfig.cs" />
|
||||
<Compile Include="ConfigurationPage\ApplicationSettings\SettingsItem.cs" />
|
||||
<Compile Include="ConfigurationPage\ApplicationSettings\ThemePreviewButton.cs" />
|
||||
|
|
|
|||
|
|
@ -70,31 +70,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication
|
|||
|
||||
public enum FirmwareTypes { Unknown, Repetier, Marlin, Sprinter };
|
||||
|
||||
public static class PrintItemWrapperExtensionMethods
|
||||
{
|
||||
private static TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
|
||||
|
||||
public static string GetFriendlyName(this PrintItemWrapper printItemWrapper)
|
||||
{
|
||||
if (printItemWrapper?.Name == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return textInfo?.ToTitleCase(printItemWrapper.Name.Replace('_', ' '));
|
||||
}
|
||||
|
||||
public static string GetFriendlyName(string fileName)
|
||||
{
|
||||
if (fileName == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return textInfo?.ToTitleCase(fileName.Replace('_', ' '));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the class that communicates with a RepRap printer over the serial port.
|
||||
/// It handles opening and closing the serial port and does quite a bit of gcode parsing.
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ either expressed or implied, of the FreeBSD Project.
|
|||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
|
|
@ -39,6 +40,31 @@ using MatterHackers.MatterControl.SlicerConfiguration;
|
|||
|
||||
namespace MatterHackers.MatterControl.PrintQueue
|
||||
{
|
||||
public static class PrintItemWrapperExtensionMethods
|
||||
{
|
||||
private static TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
|
||||
|
||||
public static string GetFriendlyName(this PrintItemWrapper printItemWrapper)
|
||||
{
|
||||
if (printItemWrapper?.Name == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return textInfo?.ToTitleCase(printItemWrapper.Name.Replace('_', ' '));
|
||||
}
|
||||
|
||||
public static string GetFriendlyName(string fileName)
|
||||
{
|
||||
if (fileName == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return textInfo?.ToTitleCase(fileName.Replace('_', ' '));
|
||||
}
|
||||
}
|
||||
|
||||
public class PrintItemWrapper
|
||||
{
|
||||
public event EventHandler SlicingDone;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue