2017-09-17 12:01:18 -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.Diagnostics ;
using System.IO ;
using System.Linq ;
using System.Threading.Tasks ;
2018-01-05 12:44:57 -08:00
using MatterControl.Printing ;
2017-09-17 12:01:18 -07:00
using MatterHackers.Agg.UI ;
using MatterHackers.MatterControl.DataStorage ;
using MatterHackers.MatterControl.PrintQueue ;
using MatterHackers.MatterControl.SlicerConfiguration ;
using Newtonsoft.Json ;
namespace MatterHackers.MatterControl
{
2018-01-06 22:03:06 -08:00
using System.Collections.Generic ;
2018-04-04 10:11:57 -07:00
using System.ComponentModel ;
2017-09-17 12:01:18 -07:00
using System.Threading ;
using MatterHackers.Agg ;
using MatterHackers.DataConverters3D ;
using MatterHackers.GCodeVisualizer ;
2018-01-06 22:03:06 -08:00
using MatterHackers.Localizations ;
2017-11-14 15:45:23 -08:00
using MatterHackers.MatterControl.Library ;
2018-01-06 22:03:06 -08:00
using MatterHackers.MatterControl.PartPreviewWindow ;
2017-09-17 12:01:18 -07:00
using MatterHackers.MatterControl.PrinterCommunication ;
2018-05-09 07:52:05 -07:00
using MatterHackers.MatterControl.PrintLibrary ;
2017-09-17 12:01:18 -07:00
using MatterHackers.MeshVisualizer ;
using MatterHackers.PolygonMesh ;
2018-05-09 08:41:29 -07:00
using MatterHackers.RenderOpenGl ;
2017-09-17 12:01:18 -07:00
using MatterHackers.VectorMath ;
2017-12-20 16:11:32 -08:00
public class BedConfig
2017-09-17 12:01:18 -07:00
{
public event EventHandler ActiveLayerChanged ;
public event EventHandler LoadedGCodeChanged ;
2017-11-29 07:35:37 -08:00
public event EventHandler SceneLoaded ;
2017-09-17 12:01:18 -07:00
public View3DConfig RendererOptions { get ; } = new View3DConfig ( ) ;
public PrinterConfig Printer { get ; set ; }
2017-11-14 15:45:23 -08:00
public EditContext EditContext { get ; private set ; }
2017-09-17 12:01:18 -07:00
public Mesh PrinterShape { get ; private set ; }
2018-05-09 08:41:29 -07:00
public SceneContextViewState ViewState { get ; }
2018-10-04 19:27:07 -07:00
private HistoryContainerBase historyContainer ;
public BedConfig ( HistoryContainerBase historyContainer , PrinterConfig printer = null )
2017-09-17 12:01:18 -07:00
{
2018-10-04 19:27:07 -07:00
this . historyContainer = historyContainer ;
2017-09-17 12:01:18 -07:00
this . Printer = printer ;
2018-05-09 08:41:29 -07:00
this . ViewState = new SceneContextViewState ( this ) ;
2017-11-14 15:45:23 -08:00
}
2017-09-17 12:01:18 -07:00
2017-11-29 08:52:29 -08:00
public async Task LoadContent ( EditContext editContext )
2017-11-14 15:45:23 -08:00
{
2018-04-04 10:11:57 -07:00
// Make sure we don't have a selection
2018-01-05 17:05:33 -08:00
this . Scene . SelectedItem = null ;
2017-12-20 15:40:30 -08:00
// Store
this . EditContext = editContext ;
2017-11-29 13:48:21 -08:00
2018-05-07 17:15:08 -07:00
var contentInfo = editContext . SourceItem as ILibraryAsset ;
if ( contentInfo ! = null )
{
this . ContentType = contentInfo . ContentType ;
}
2017-12-20 15:40:30 -08:00
// Load
2018-02-12 13:55:31 -08:00
if ( editContext . SourceItem is ILibraryAssetStream contentStream
2017-11-29 13:48:21 -08:00
& & contentStream . ContentType = = "gcode" )
{
2018-02-12 14:32:18 -08:00
using ( var task = await contentStream . GetStream ( null ) )
2017-11-29 13:48:21 -08:00
{
2017-12-20 16:11:32 -08:00
await LoadGCodeContent ( task . Stream ) ;
2017-11-29 13:48:21 -08:00
}
this . Scene . Children . Modify ( children = > children . Clear ( ) ) ;
2018-05-07 17:36:30 -07:00
editContext . FreezeGCode = true ;
2017-11-29 13:48:21 -08:00
}
else
{
2018-01-29 16:58:55 -08:00
// Load last item or fall back to empty if unsuccessful
editContext . Content = await editContext . SourceItem . CreateContent ( null ) ? ? new Object3D ( ) ;
2017-11-29 13:48:21 -08:00
this . Scene . Load ( editContext . Content ) ;
}
2017-11-29 08:52:29 -08:00
// Notify
this . SceneLoaded ? . Invoke ( this , null ) ;
2017-11-14 15:45:23 -08:00
}
2017-12-20 16:11:32 -08:00
2018-05-22 13:41:16 -07:00
public async Task LoadGCodeContent ( Stream stream )
2017-12-20 16:11:32 -08:00
{
2018-02-20 18:27:52 -08:00
await ApplicationController . Instance . Tasks . Execute ( "Loading G-Code" . Localize ( ) , ( reporter , cancellationToken ) = >
2017-12-20 16:11:32 -08:00
{
2018-02-20 18:27:52 -08:00
var progressStatus = new ProgressStatus ( ) ;
2017-12-20 16:11:32 -08:00
reporter . Report ( progressStatus ) ;
this . LoadGCode ( stream , cancellationToken , ( progress0To1 , status ) = >
{
progressStatus . Status = status ;
progressStatus . Progress0To1 = progress0To1 ;
reporter . Report ( progressStatus ) ;
} ) ;
return Task . CompletedTask ;
} ) ;
}
2017-09-17 12:01:18 -07:00
2017-11-30 06:10:46 -08:00
internal async Task ClearPlate ( )
2017-09-17 12:01:18 -07:00
{
2017-10-17 12:55:58 -07:00
// Clear existing
this . LoadedGCode = null ;
this . GCodeRenderer = null ;
2018-05-07 17:36:30 -07:00
// Switch back to Model view on ClearPlate
if ( this . Printer ! = null )
{
this . Printer . ViewState . ViewMode = PartViewMode . Model ;
}
2017-11-29 08:52:29 -08:00
// Load
2017-11-30 06:10:46 -08:00
await this . LoadContent ( new EditContext ( )
2017-11-29 08:52:29 -08:00
{
2018-04-29 11:05:35 -07:00
ContentStore = historyContainer ,
2018-10-04 19:27:07 -07:00
SourceItem = historyContainer . NewPlatingItem ( )
2017-11-30 06:10:46 -08:00
} ) ;
2017-09-17 12:01:18 -07:00
}
2018-09-25 09:52:54 -07:00
public InsertionGroupObject3D AddToPlate ( IEnumerable < ILibraryItem > itemsToAdd )
2017-11-30 06:51:06 -08:00
{
2018-09-25 16:21:32 -07:00
InsertionGroupObject3D insertionGroup = null ;
2017-11-30 06:51:06 -08:00
2018-09-25 16:21:32 -07:00
var context = ApplicationController . Instance . DragDropData ;
var scene = context . SceneContext . Scene ;
scene . Children . Modify ( list = >
2017-11-30 06:51:06 -08:00
{
2018-09-25 16:21:32 -07:00
list . Add (
insertionGroup = new InsertionGroupObject3D (
itemsToAdd ,
context . View3DWidget ,
scene ,
2018-09-26 13:23:03 -07:00
( Printer ! = null ) ? Printer . Bed . BedCenter : Vector2 . Zero ,
2018-09-25 16:21:32 -07:00
( item , itemsToAvoid ) = >
{
PlatingHelper . MoveToOpenPositionRelativeGroup ( item , itemsToAvoid ) ;
} ) ) ;
} ) ;
2018-09-25 09:52:54 -07:00
2018-09-25 16:21:32 -07:00
return insertionGroup ;
2017-11-30 06:51:06 -08:00
}
2018-10-04 19:28:41 -07:00
/// <summary>
/// Loads content to the bed and prepares edit/persistence context for use
/// </summary>
/// <param name="editContext"></param>
/// <returns></returns>
public async Task LoadPlateFromHistory ( )
{
await this . LoadContent ( new EditContext ( )
{
ContentStore = historyContainer ,
SourceItem = historyContainer . GetLastPlateOrNew ( )
} ) ;
}
2018-07-18 14:59:23 -07:00
public async Task StashAndPrintGCode ( ILibraryItem libraryItem )
{
// Clear plate
await this . ClearPlate ( ) ;
// Add content
await this . LoadContent (
new EditContext ( )
{
SourceItem = libraryItem ,
2018-10-04 19:42:58 -07:00
// No content store for GCode
ContentStore = null
2018-07-18 14:59:23 -07:00
} ) ;
// Slice and print
await ApplicationController . Instance . PrintPart (
this . EditContext ,
this . Printer ,
null ,
CancellationToken . None ) ;
}
2017-11-30 07:03:42 -08:00
public async Task StashAndPrint ( IEnumerable < ILibraryItem > selectedLibraryItems )
{
// Clear plate
await this . ClearPlate ( ) ;
// Add content
var insertionGroup = this . AddToPlate ( selectedLibraryItems ) ;
await insertionGroup . LoadingItemsTask ;
// Persist changes
2018-02-13 17:00:23 -08:00
await this . SaveChanges ( null , CancellationToken . None ) ;
2017-11-30 07:03:42 -08:00
// Slice and print
await ApplicationController . Instance . PrintPart (
2018-02-09 18:11:55 -08:00
this . EditContext ,
2017-11-30 07:03:42 -08:00
this . Printer ,
2017-12-11 14:15:50 -08:00
null ,
CancellationToken . None ) ;
2017-11-30 07:03:42 -08:00
}
2017-09-17 12:01:18 -07:00
private GCodeFile loadedGCode ;
public GCodeFile LoadedGCode
{
get = > loadedGCode ;
2017-12-24 10:25:41 -08:00
private set
2017-09-17 12:01:18 -07:00
{
if ( loadedGCode ! = value )
{
loadedGCode = value ;
LoadedGCodeChanged ? . Invoke ( null , null ) ;
}
}
}
2017-12-24 10:23:56 -08:00
internal void EnsureGCodeLoaded ( )
{
2018-10-04 19:27:07 -07:00
if ( this . LoadedGCode = = null
2017-12-24 10:23:56 -08:00
& & File . Exists ( this . EditContext ? . GCodeFilePath ) )
{
UiThread . RunOnIdle ( async ( ) = >
{
using ( var stream = File . OpenRead ( this . EditContext . GCodeFilePath ) )
{
await LoadGCodeContent ( stream ) ;
}
} ) ;
}
}
2017-09-17 12:01:18 -07:00
public WorldView World { get ; } = new WorldView ( 0 , 0 ) ;
2017-09-20 15:29:30 -07:00
public double BuildHeight { get ; internal set ; }
2017-09-17 12:01:18 -07:00
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 ; }
2017-12-24 10:40:30 -08:00
private int _activeLayerIndex ;
2017-09-17 12:01:18 -07:00
public int ActiveLayerIndex
{
2017-12-24 10:40:30 -08:00
get = > _activeLayerIndex ;
2017-09-17 12:01:18 -07:00
set
{
2017-12-24 10:40:30 -08:00
if ( _activeLayerIndex ! = value )
2017-09-17 12:01:18 -07:00
{
2017-12-24 10:40:30 -08:00
_activeLayerIndex = value ;
2017-09-17 12:01:18 -07:00
// Clamp activeLayerIndex to valid range
2017-12-24 10:40:30 -08:00
if ( this . GCodeRenderer = = null | | _activeLayerIndex < 0 )
2017-09-17 12:01:18 -07:00
{
2017-12-24 10:40:30 -08:00
_activeLayerIndex = 0 ;
2017-09-17 12:01:18 -07:00
}
2017-12-24 10:40:30 -08:00
else if ( _activeLayerIndex > = this . LoadedGCode . LayerCount )
2017-09-17 12:01:18 -07:00
{
2017-12-24 10:40:30 -08:00
_activeLayerIndex = this . LoadedGCode . LayerCount - 1 ;
2017-09-17 12:01:18 -07:00
}
// When the active layer changes we update the selected range accordingly - constrain to applicable values
2017-09-24 18:50:51 -07:00
if ( this . RenderInfo ! = null )
{
2017-10-21 20:22:14 -07:00
// TODO: Unexpected that rendering layer 2 requires that we set the range to 0-3. Seems like model should be updated to allow 0-2 to mean render up to layer 2
2017-12-24 10:40:30 -08:00
this . RenderInfo . EndLayerIndex = Math . Min ( this . LoadedGCode = = null ? 0 : this . LoadedGCode . LayerCount , Math . Max ( _activeLayerIndex + 1 , 1 ) ) ;
2017-09-24 18:50:51 -07:00
}
2017-09-17 12:01:18 -07:00
ActiveLayerChanged ? . Invoke ( this , null ) ;
}
}
}
public InteractiveScene Scene { get ; } = new InteractiveScene ( ) ;
public GCodeRenderInfo RenderInfo { get ; set ; }
private Mesh _bedMesh ;
public Mesh Mesh
{
get
{
if ( _bedMesh = = null )
{
2017-11-16 16:34:27 -08:00
// Load bed and build volume meshes
2018-04-19 14:37:54 -07:00
( _bedMesh , _buildVolumeMesh ) = BedMeshGenerator . CreatePrintBedAndVolume ( Printer ) ;
2017-09-17 12:01:18 -07:00
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 ) )
{
2018-07-31 13:15:06 -07:00
var mesh = Object3D . Load ( stream , extension , CancellationToken . None ) . Mesh ;
2017-09-17 12:01:18 -07:00
BspNode bspTree = null ;
2018-04-19 13:26:19 -07:00
// if there is a cached bsp tree load it
2017-09-17 12:01:18 -07:00
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 ;
2018-04-19 13:26:19 -07:00
public Mesh BuildVolumeMesh = > _buildVolumeMesh ;
2017-09-17 12:01:18 -07:00
2018-05-07 17:36:30 -07:00
public bool EditableScene
{
get = > this . EditContext ? . FreezeGCode ! = true ;
}
2017-11-29 13:48:21 -08:00
2018-05-07 17:15:08 -07:00
public string ContentType { get ; private set ; }
2018-03-14 15:25:39 -07:00
internal void RenderGCode3D ( DrawEventArgs e )
2017-09-17 12:01:18 -07:00
{
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 )
{
2018-01-31 09:50:23 -08:00
if ( File . Exists ( filePath ) )
2017-11-29 08:52:29 -08:00
{
2018-01-31 09:50:23 -08:00
using ( var stream = File . OpenRead ( filePath ) )
{
this . LoadGCode ( stream , cancellationToken , progressReporter ) ;
}
2017-11-29 08:52:29 -08:00
}
}
2017-11-29 15:22:18 -08:00
private RenderType GetRenderType ( )
{
var options = this . RendererOptions ;
RenderType renderType = RenderType . Extrusions ;
if ( options . RenderMoves )
{
renderType | = RenderType . Moves ;
}
if ( options . RenderRetractions )
{
renderType | = RenderType . Retractions ;
}
2018-02-09 19:23:19 -08:00
2018-04-04 10:11:57 -07:00
if ( options . GCodeLineColorStyle = = "Speeds" )
2017-11-29 15:22:18 -08:00
{
renderType | = RenderType . SpeedColors ;
}
2018-02-09 19:23:19 -08:00
else if ( options . GCodeLineColorStyle ! = "Materials" )
{
renderType | = RenderType . GrayColors ;
}
2017-11-29 15:22:18 -08:00
if ( options . SimulateExtrusion )
{
renderType | = RenderType . SimulateExtrusion ;
}
if ( options . TransparentExtrusion )
{
renderType | = RenderType . TransparentExtrusion ;
}
if ( options . HideExtruderOffsets )
{
renderType | = RenderType . HideExtruderOffsets ;
}
return renderType ;
}
2017-11-29 08:52:29 -08:00
public void LoadGCode ( Stream stream , CancellationToken cancellationToken , Action < double , string > progressReporter )
{
2018-01-17 14:03:56 -08:00
var settings = this . Printer . Settings ;
var maxAcceleration = settings . GetValue < double > ( SettingsKey . max_acceleration ) ;
var maxVelocity = settings . GetValue < double > ( SettingsKey . max_velocity ) ;
var jerkVelocity = settings . GetValue < double > ( SettingsKey . jerk_velocity ) ;
2018-02-02 09:47:06 -08:00
var multiplier = settings . GetValue < double > ( SettingsKey . print_time_estimate_multiplier ) / 100.0 ;
2018-01-17 14:03:56 -08:00
var loadedGCode = GCodeMemoryFile . Load ( stream ,
new Vector4 ( maxAcceleration , maxAcceleration , maxAcceleration , maxAcceleration ) ,
new Vector4 ( maxVelocity , maxVelocity , maxVelocity , maxVelocity ) ,
new Vector4 ( jerkVelocity , jerkVelocity , jerkVelocity , jerkVelocity ) ,
2018-02-02 09:47:06 -08:00
new Vector4 ( multiplier , multiplier , multiplier , multiplier ) ,
2018-01-17 14:03:56 -08:00
cancellationToken , progressReporter ) ;
2017-09-17 12:01:18 -07:00
this . GCodeRenderer = new GCodeRenderer ( loadedGCode ) ;
2018-06-11 13:17:22 -07:00
2017-11-29 15:22:18 -08:00
this . RenderInfo = new GCodeRenderInfo (
0 ,
2018-06-11 13:17:22 -07:00
// Renderer requires endLayerIndex to be desiredLayer+1: to render layer zero we set endLayerIndex to 1
Math . Max ( 1 , this . ActiveLayerIndex + 1 ) ,
2017-11-29 15:22:18 -08:00
Agg . Transform . Affine . NewIdentity ( ) ,
1 ,
0 ,
1 ,
new Vector2 [ ]
{
2018-01-17 14:03:56 -08:00
settings . Helpers . ExtruderOffset ( 0 ) ,
settings . Helpers . ExtruderOffset ( 1 )
2017-11-29 15:22:18 -08:00
} ,
this . GetRenderType ,
MeshViewerWidget . GetExtruderColor ) ;
2017-09-17 12:01:18 -07:00
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 ) ;
}
2017-12-24 10:35:21 -08:00
// Assign property causing event and UI load
this . LoadedGCode = loadedGCode ;
2017-12-24 10:36:49 -08:00
// Constrain to max layers
if ( this . ActiveLayerIndex > loadedGCode . LayerCount )
{
this . ActiveLayerIndex = loadedGCode . LayerCount ;
}
ActiveLayerChanged ? . Invoke ( this , null ) ;
2017-09-17 12:01:18 -07:00
}
2017-09-20 15:32:22 -07:00
public void InvalidateBedMesh ( )
2017-09-17 12:01:18 -07:00
{
2017-09-20 15:32:22 -07:00
// Invalidate bed mesh cache
2017-09-20 15:29:30 -07:00
_bedMesh = null ;
2017-09-17 12:01:18 -07:00
}
2017-11-14 15:45:23 -08:00
2018-02-13 17:00:23 -08:00
/// <summary>
/// Persists modified meshes to assets and saves pending changes back to the EditContext
/// </summary>
/// <param name="progress"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
2018-02-10 21:28:11 -08:00
public Task SaveChanges ( IProgress < ProgressStatus > progress , CancellationToken cancellationToken )
{
var progressStatus = new ProgressStatus ( )
{
Status = "Saving Changes"
} ;
2018-02-13 17:00:23 -08:00
progress ? . Report ( progressStatus ) ;
2018-02-10 21:28:11 -08:00
2017-11-14 15:45:23 -08:00
if ( this . Scene . Persistable )
{
2018-02-13 17:00:23 -08:00
this . Scene . PersistAssets ( ( progress0to1 , status ) = >
{
if ( progress ! = null )
{
progressStatus . Status = status ;
progressStatus . Progress0To1 = progress0to1 ;
progress . Report ( progressStatus ) ;
}
} ) ;
2017-12-18 13:16:40 -08:00
this . EditContext ? . Save ( ) ;
2017-11-14 15:45:23 -08:00
}
2018-02-13 17:00:23 -08:00
return Task . CompletedTask ;
2017-11-14 15:45:23 -08:00
}
2018-04-02 16:19:45 -07:00
public List < BoolOption > GetBaseViewOptions ( )
{
2018-04-05 15:42:10 -07:00
return new List < BoolOption > ( ) ;
2018-04-02 16:19:45 -07:00
}
2017-11-14 15:45:23 -08:00
}
public class EditContext
{
2017-11-15 07:41:36 -08:00
private ILibraryItem _sourceItem ;
2017-11-15 09:22:36 -08:00
public IContentStore ContentStore { get ; set ; }
2017-11-15 07:41:36 -08:00
public ILibraryItem SourceItem
{
get = > _sourceItem ;
set
{
if ( _sourceItem ! = value )
{
_sourceItem = value ;
if ( _sourceItem is FileSystemFileItem fileItem )
{
printItem = new PrintItemWrapper ( new PrintItem ( fileItem . FileName , fileItem . Path ) ) ;
}
}
}
}
2017-11-15 09:22:36 -08:00
2017-11-14 15:45:23 -08:00
public IObject3D Content { get ; set ; }
2018-05-26 12:16:23 -07:00
// Natural path
private string gcodePath = > printItem ? . GetGCodePathAndFileName ( ) ;
// Override path
public string GCodeOverridePath = > Path . ChangeExtension ( gcodePath , GCodeFile . PostProcessedExtension ) ;
// Override or natural path
public string GCodeFilePath = > ( File . Exists ( this . GCodeOverridePath ) ) ? this . GCodeOverridePath : gcodePath ;
2017-11-15 07:41:36 -08:00
2018-02-09 18:11:55 -08:00
public string SourceFilePath = > printItem ? . FileLocation ;
2017-11-15 07:41:36 -08:00
2018-05-07 17:36:30 -07:00
public bool FreezeGCode { get ; set ; }
2017-11-15 07:41:36 -08:00
/// <summary>
/// Short term stop gap that should only be used until GCode path helpers, hash code and print recovery components can be extracted
/// </summary>
[Obsolete]
internal PrintItemWrapper printItem { get ; set ; }
2017-11-14 15:45:23 -08:00
internal void Save ( )
{
2018-05-07 17:36:30 -07:00
if ( ! this . FreezeGCode )
2017-11-14 16:54:27 -08:00
{
2018-08-02 15:59:06 -07:00
ApplicationController . Instance . Thumbnails . DeleteCache ( this . SourceItem ) ;
2018-02-03 13:27:02 -08:00
2017-11-29 13:48:21 -08:00
// Call save on the provider
2018-10-04 19:42:58 -07:00
this . ContentStore ? . Save ( this . SourceItem , this . Content ) ;
2017-11-29 13:48:21 -08:00
}
2017-11-14 15:45:23 -08:00
}
2017-09-17 12:01:18 -07:00
}
2018-05-09 07:52:05 -07:00
public class AppViewState
{
public PrintLibraryWidget . ListViewModes LibraryViewMode { get ; set ; } = PrintLibraryWidget . ListViewModes . IconListView ;
}
2018-05-09 08:41:29 -07:00
public class SceneContextViewState
{
private BedConfig sceneContext ;
2018-09-14 15:20:19 -07:00
private RenderTypes renderType = RenderTypes . Outlines ;
2018-05-09 08:41:29 -07:00
public SceneContextViewState ( BedConfig sceneContext )
{
this . sceneContext = sceneContext ;
// Make sure the render mode is set correctly
string renderTypeString = UserSettings . Instance . get ( UserSettingsKey . defaultRenderSetting ) ;
if ( renderTypeString = = null )
{
2018-09-14 15:20:19 -07:00
renderTypeString = "Outlines" ;
2018-05-09 08:41:29 -07:00
UserSettings . Instance . set ( UserSettingsKey . defaultRenderSetting , renderTypeString ) ;
}
if ( Enum . TryParse ( renderTypeString , out renderType ) )
{
this . RenderType = renderType ;
}
}
public bool ModelView { get ; set ; } = true ;
public RenderTypes RenderType
{
2018-09-11 14:05:54 -07:00
get = > this . ModelView ? renderType : RenderTypes . Shaded ;
2018-05-09 08:41:29 -07:00
set
{
if ( renderType ! = value )
{
renderType = value ;
// Persist value
UserSettings . Instance . set ( UserSettingsKey . defaultRenderSetting , renderType . ToString ( ) ) ;
foreach ( var renderTransfrom in sceneContext . Scene . VisibleMeshes ( ) )
{
2018-05-29 17:46:59 -07:00
renderTransfrom . Mesh . MarkAsChanged ( ) ;
2018-05-09 08:41:29 -07:00
}
}
}
}
2018-05-31 20:07:49 -07:00
2018-09-10 18:24:09 -07:00
public double SceneTreeRatio
2018-05-31 20:07:49 -07:00
{
get
{
2018-09-10 18:24:09 -07:00
if ( double . TryParse ( UserSettings . Instance . get ( UserSettingsKey . SceneTreeRatio ) , out double treeRatio ) )
2018-05-31 20:07:49 -07:00
{
2018-09-10 18:24:09 -07:00
return treeRatio ;
2018-05-31 20:07:49 -07:00
}
2018-09-10 18:24:09 -07:00
return . 75 ;
2018-05-31 20:07:49 -07:00
}
set
{
2018-09-10 18:24:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . SceneTreeRatio , value . ToString ( ) ) ;
2018-05-31 20:07:49 -07:00
}
}
public double SelectedObjectEditorHeight
{
get
{
if ( double . TryParse ( UserSettings . Instance . get ( UserSettingsKey . SelectedObjectEditorHeight ) , out double controlHeight ) )
{
return Math . Max ( controlHeight , 35 ) ;
}
return 120 ;
}
set
{
var minimumValue = Math . Max ( value , 35 ) ;
UserSettings . Instance . set ( UserSettingsKey . SelectedObjectEditorHeight , minimumValue . ToString ( ) ) ;
}
}
2018-05-09 08:41:29 -07:00
}
2017-09-17 12:01:18 -07:00
public class PrinterViewState
{
2017-11-27 17:36:36 -08:00
public event EventHandler < ViewModeChangedEventArgs > ViewModeChanged ;
2018-09-08 12:52:47 -07:00
public event EventHandler VisibilityChanged ;
2018-01-03 15:24:55 -08:00
2017-09-17 12:01:18 -07:00
public bool SliceSettingsTabPinned
{
get = > UserSettings . Instance . get ( UserSettingsKey . SliceSettingsTabPinned ) = = "true" ;
set
{
UserSettings . Instance . set ( UserSettingsKey . SliceSettingsTabPinned , value ? "true" : "false" ) ;
}
}
2018-09-07 14:49:26 -07:00
public string SliceSettingsTabKey
2017-09-17 12:01:18 -07:00
{
get
{
2018-09-07 14:49:26 -07:00
return UserSettings . Instance . get ( UserSettingsKey . SliceSettingsTabIndex ) ;
2017-09-17 12:01:18 -07:00
}
set
{
2018-09-07 14:49:26 -07:00
UserSettings . Instance . set ( UserSettingsKey . SliceSettingsTabIndex , value ) ;
2017-09-17 12:01:18 -07:00
}
}
2017-11-07 11:31:30 -08:00
public bool DockWindowFloating { get ; internal set ; }
2018-01-25 09:02:33 -08:00
double DefaultSliceSettingsWidth = > 450 ;
2017-09-17 12:01:18 -07:00
public double SliceSettingsWidth
{
get
{
double . TryParse ( UserSettings . Instance . get ( UserSettingsKey . SliceSettingsWidth ) , out double controlWidth ) ;
2018-01-25 09:02:33 -08:00
if ( controlWidth = = 0 )
{
controlWidth = DefaultSliceSettingsWidth ;
}
2017-09-17 12:01:18 -07:00
return controlWidth ;
}
set
{
UserSettings . Instance . set ( UserSettingsKey . SliceSettingsWidth , value . ToString ( ) ) ;
}
}
2017-11-27 17:36:36 -08:00
private PartViewMode viewMode = PartViewMode . Model ;
public PartViewMode ViewMode
{
get = > viewMode ;
set
{
if ( viewMode ! = value )
{
viewMode = value ;
ViewModeChanged ? . Invoke ( this , new ViewModeChangedEventArgs ( )
{
ViewMode = this . ViewMode
} ) ;
}
}
}
2018-01-03 15:24:55 -08:00
2018-03-12 15:59:03 -07:00
public bool _configurePrinterVisible = UserSettings . Instance . get ( UserSettingsKey . ConfigurePrinterTabVisible ) = = "true" ;
2018-09-10 13:35:54 -07:00
// set the controls to default to visible
public bool _controlsVisible = UserSettings . Instance . get ( UserSettingsKey . ControlsTabVisible ) ! = "false" ;
2018-09-07 14:49:26 -07:00
public bool _terminalVisible = UserSettings . Instance . get ( UserSettingsKey . TerminalTabVisible ) = = "true" ;
2018-01-03 15:24:55 -08:00
public bool ConfigurePrinterVisible
{
get = > _configurePrinterVisible ;
set
{
if ( _configurePrinterVisible ! = value )
{
if ( value )
{
2018-09-07 14:49:26 -07:00
this . SliceSettingsTabKey = "Printer" ;
2018-01-03 15:24:55 -08:00
}
_configurePrinterVisible = value ;
2018-03-12 15:59:03 -07:00
UserSettings . Instance . set ( UserSettingsKey . ConfigurePrinterTabVisible , _configurePrinterVisible ? "true" : "false" ) ;
2018-09-08 12:52:47 -07:00
VisibilityChanged ? . Invoke ( this , null ) ;
2018-09-07 14:49:26 -07:00
}
}
}
public bool ControlsVisible
{
get = > _controlsVisible ;
set
{
if ( _controlsVisible ! = value )
{
if ( value )
{
this . SliceSettingsTabKey = "Controls" ;
}
_controlsVisible = value ;
UserSettings . Instance . set ( UserSettingsKey . ControlsTabVisible , _controlsVisible ? "true" : "false" ) ;
2018-09-08 12:52:47 -07:00
VisibilityChanged ? . Invoke ( this , null ) ;
2018-09-07 14:49:26 -07:00
}
}
}
public bool TerminalVisible
{
get = > _terminalVisible ;
set
{
if ( _terminalVisible ! = value )
{
if ( value )
{
this . SliceSettingsTabKey = "Terminal" ;
}
_terminalVisible = value ;
UserSettings . Instance . set ( UserSettingsKey . TerminalTabVisible , _terminalVisible ? "true" : "false" ) ;
2018-09-08 12:52:47 -07:00
VisibilityChanged ? . Invoke ( this , null ) ;
2018-01-03 15:24:55 -08:00
}
}
}
2018-01-08 21:25:36 -08:00
public double SelectedObjectPanelWidth
{
get
{
if ( double . TryParse ( UserSettings . Instance . get ( UserSettingsKey . SelectedObjectPanelWidth ) , out double controlWidth ) )
{
2018-01-09 18:41:21 -08:00
return Math . Max ( controlWidth , 150 ) ;
2018-01-08 21:25:36 -08:00
}
return 200 ;
}
set
{
2018-01-09 18:41:21 -08:00
var minimumValue = Math . Max ( value , 150 ) ;
UserSettings . Instance . set ( UserSettingsKey . SelectedObjectPanelWidth , minimumValue . ToString ( ) ) ;
2018-01-08 21:25:36 -08:00
}
}
2017-09-17 12:01:18 -07:00
}
public class PrinterConfig
{
public BedConfig Bed { get ; }
2017-12-20 18:25:12 -08:00
private EventHandler unregisterEvents ;
2018-10-04 19:13:18 -07:00
public static PrinterConfig EmptyPrinter { get ; } = new PrinterConfig ( ) ;
private PrinterConfig ( )
{
this . Connection = new PrinterConnection ( this ) ;
}
2017-12-20 18:25:12 -08:00
public PrinterConfig ( PrinterSettings settings )
{
2018-10-04 19:27:07 -07:00
this . Bed = new BedConfig ( ApplicationController . Instance . Library . PlatingHistory , this ) ;
2018-05-09 10:50:31 -07:00
this . ViewState = new PrinterViewState ( ) ;
2018-10-04 19:27:07 -07:00
this . Connection = new PrinterConnection ( this ) ;
2017-12-20 18:25:12 -08:00
this . Settings = settings ;
this . Settings . printer = this ;
2018-01-06 13:26:28 -08:00
// TODO: ActiveSliceSettings is not our Settings! Move SettingsChanged to instance rather than static
2017-12-20 18:25:12 -08:00
ActiveSliceSettings . SettingChanged . RegisterEvent ( Printer_SettingChanged , ref unregisterEvents ) ;
2018-01-06 13:26:28 -08:00
this . Connection . PrintFinished . RegisterEvent ( ( s , e ) = >
{
// clear single use setting on print completion
foreach ( var keyValue in this . Settings . BaseLayer )
{
string currentValue = this . Settings . GetValue ( keyValue . Key ) ;
bool valueIsClear = currentValue = = "0" | currentValue = = "" ;
2018-01-13 18:54:40 -08:00
SliceSettingData data = SettingsOrganizer . Instance . GetSettingsData ( keyValue . Key ) ;
2018-01-06 13:26:28 -08:00
if ( data ? . ResetAtEndOfPrint = = true & & ! valueIsClear )
{
this . Settings . ClearValue ( keyValue . Key ) ;
}
}
} , ref unregisterEvents ) ;
if ( ! string . IsNullOrEmpty ( this . Settings . GetValue ( SettingsKey . baud_rate ) ) )
{
this . Connection . BaudRate = this . Settings . GetValue < int > ( SettingsKey . baud_rate ) ;
}
this . Connection . ConnectGCode = this . Settings . GetValue ( SettingsKey . connect_gcode ) ;
this . Connection . CancelGCode = this . Settings . GetValue ( SettingsKey . cancel_gcode ) ;
this . Connection . EnableNetworkPrinting = this . Settings . GetValue < bool > ( SettingsKey . enable_network_printing ) ;
this . Connection . AutoReleaseMotors = this . Settings . GetValue < bool > ( SettingsKey . auto_release_motors ) ;
this . Connection . RecoveryIsEnabled = this . Settings . GetValue < bool > ( SettingsKey . recover_is_enabled ) ;
this . Connection . ExtruderCount = this . Settings . GetValue < int > ( SettingsKey . extruder_count ) ;
this . Connection . SendWithChecksum = this . Settings . GetValue < bool > ( SettingsKey . send_with_checksum ) ;
2018-01-06 16:03:03 -08:00
this . Connection . ReadLineReplacementString = this . Settings . GetValue ( SettingsKey . read_regex ) ;
2018-01-06 13:26:28 -08:00
}
2018-05-09 08:41:29 -07:00
public PrinterViewState ViewState { get ; }
2017-09-20 15:29:30 -07:00
2018-10-04 19:13:18 -07:00
private PrinterSettings _settings = PrinterSettings . Empty ;
2017-09-20 15:29:30 -07:00
public PrinterSettings Settings
{
get = > _settings ;
private set
{
if ( _settings ! = value )
{
_settings = value ;
this . ReloadSettings ( ) ;
2017-09-20 15:32:22 -07:00
this . Bed . InvalidateBedMesh ( ) ;
2017-09-20 15:29:30 -07:00
}
}
}
2017-09-17 13:30:05 -07:00
public PrinterConnection Connection { get ; private set ; }
2017-09-17 12:01:18 -07:00
2017-12-29 16:12:52 -08:00
public string PrinterConnectionStatus
{
get
{
switch ( this . Connection . CommunicationState )
{
case CommunicationStates . Disconnected :
return "Not Connected" . Localize ( ) ;
case CommunicationStates . Disconnecting :
return "Disconnecting" . Localize ( ) ;
case CommunicationStates . AttemptingToConnect :
return "Connecting" . Localize ( ) + "..." ;
case CommunicationStates . ConnectionLost :
return "Connection Lost" . Localize ( ) ;
case CommunicationStates . FailedToConnect :
return "Unable to Connect" . Localize ( ) ;
case CommunicationStates . Connected :
return "Connected" . Localize ( ) ;
case CommunicationStates . PreparingToPrint :
return "Preparing To Print" . Localize ( ) ;
case CommunicationStates . Printing :
switch ( this . Connection . DetailedPrintingState )
{
case DetailedPrintingState . HomingAxis :
return "Homing" . Localize ( ) ;
case DetailedPrintingState . HeatingBed :
return "Waiting for Bed to Heat to" . Localize ( ) + $" {this.Connection.TargetBedTemperature}°" ;
case DetailedPrintingState . HeatingExtruder :
return "Waiting for Extruder to Heat to" . Localize ( ) + $" {this.Connection.GetTargetHotendTemperature(0)}°" ;
case DetailedPrintingState . Printing :
default :
return "Printing" . Localize ( ) ;
}
case CommunicationStates . PrintingFromSd :
return "Printing From SD Card" . Localize ( ) ;
case CommunicationStates . Paused :
return "Paused" . Localize ( ) ;
case CommunicationStates . FinishedPrint :
return "Finished Print" . Localize ( ) ;
default :
throw new NotImplementedException ( "Make sure every status returns the correct connected state." ) ;
}
}
}
2017-09-23 14:44:43 -07:00
internal void SwapToSettings ( PrinterSettings printerSettings )
{
_settings = printerSettings ;
ApplicationController . Instance . ReloadAll ( ) ;
}
2017-09-17 12:01:18 -07:00
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 ( ) ;
2017-09-20 15:32:22 -07:00
this . Bed . InvalidateBedMesh ( ) ;
2017-09-17 12:01:18 -07:00
}
2018-01-06 13:26:28 -08:00
// Sync settings changes to printer connection
switch ( stringEvent . Data )
{
case SettingsKey . feedrate_ratio :
this . Connection . FeedRateRatio = this . Settings . GetValue < double > ( SettingsKey . feedrate_ratio ) ;
break ;
case SettingsKey . baud_rate :
if ( ! string . IsNullOrEmpty ( this . Settings . GetValue ( SettingsKey . baud_rate ) ) )
{
this . Connection . BaudRate = this . Settings . GetValue < int > ( SettingsKey . baud_rate ) ;
}
break ;
case SettingsKey . connect_gcode :
this . Connection . ConnectGCode = this . Settings . GetValue ( SettingsKey . connect_gcode ) ;
break ;
case SettingsKey . cancel_gcode :
this . Connection . CancelGCode = this . Settings . GetValue ( SettingsKey . cancel_gcode ) ;
break ;
case SettingsKey . enable_network_printing :
this . Connection . EnableNetworkPrinting = this . Settings . GetValue < bool > ( SettingsKey . enable_network_printing ) ;
break ;
case SettingsKey . auto_release_motors :
this . Connection . AutoReleaseMotors = this . Settings . GetValue < bool > ( SettingsKey . auto_release_motors ) ;
break ;
case SettingsKey . recover_is_enabled :
this . Connection . RecoveryIsEnabled = this . Settings . GetValue < bool > ( SettingsKey . recover_is_enabled ) ;
break ;
case SettingsKey . extruder_count :
this . Connection . ExtruderCount = this . Settings . GetValue < int > ( SettingsKey . extruder_count ) ;
break ;
case SettingsKey . send_with_checksum :
this . Connection . SendWithChecksum = this . Settings . GetValue < bool > ( SettingsKey . send_with_checksum ) ;
break ;
2018-01-06 16:03:03 -08:00
case SettingsKey . read_regex :
this . Connection . ReadLineReplacementString = this . Settings . GetValue ( SettingsKey . read_regex ) ;
break ;
2018-01-06 13:26:28 -08:00
}
2017-09-17 12:01:18 -07:00
}
}
}
2018-04-04 10:11:57 -07:00
public class View3DConfig : INotifyPropertyChanged
2017-09-17 12:01:18 -07:00
{
2018-04-04 10:11:57 -07:00
public event PropertyChangedEventHandler PropertyChanged ;
2017-09-17 12:01:18 -07:00
2018-04-04 10:11:57 -07:00
public bool IsDirty { get ; internal set ; }
2018-02-09 19:23:19 -08:00
2017-11-20 13:09:52 -08:00
public bool RenderBed
2017-09-17 12:01:18 -07:00
{
get
{
2018-04-18 14:38:09 -07:00
string value = UserSettings . Instance . get ( UserSettingsKey . GcodeViewerRenderGrid ) ;
2017-09-17 12:01:18 -07:00
if ( value = = null )
{
return true ;
}
return ( value = = "True" ) ;
}
set
{
2018-04-04 10:11:57 -07:00
if ( this . RenderBed ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeViewerRenderGrid , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( RenderBed ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
public bool RenderMoves
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . GcodeViewerRenderMoves ) = = "True" ;
2017-09-17 12:01:18 -07:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . RenderMoves ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeViewerRenderMoves , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( RenderMoves ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
public bool RenderRetractions
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . GcodeViewerRenderRetractions ) = = "True" ;
2017-09-17 12:01:18 -07:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . RenderRetractions ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeViewerRenderRetractions , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( RenderRetractions ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
2018-02-02 18:19:23 -08:00
public string GCodeModelView
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . GcodeModelView ) ;
2018-02-02 18:19:23 -08:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . GCodeModelView ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeModelView , value ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( GCodeModelView ) ) ;
}
2018-02-02 18:19:23 -08:00
}
}
2018-02-09 19:23:19 -08:00
public string GCodeLineColorStyle
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . GCodeLineColorStyle ) ;
2018-02-09 19:23:19 -08:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . GCodeLineColorStyle ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GCodeLineColorStyle , value ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( GCodeLineColorStyle ) ) ;
}
2018-02-09 19:23:19 -08:00
}
}
2017-09-17 12:01:18 -07:00
public bool SimulateExtrusion
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . GcodeViewerSimulateExtrusion ) = = "True" ;
2017-09-17 12:01:18 -07:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . SimulateExtrusion ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeViewerSimulateExtrusion , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( SimulateExtrusion ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
public bool TransparentExtrusion
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . GcodeViewerTransparentExtrusion ) = = "True" ;
2017-09-17 12:01:18 -07:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . TransparentExtrusion ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeViewerTransparentExtrusion , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( TransparentExtrusion ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
public bool HideExtruderOffsets
{
get
{
2018-04-18 14:38:09 -07:00
string value = UserSettings . Instance . get ( UserSettingsKey . GcodeViewerHideExtruderOffsets ) ;
2017-09-17 12:01:18 -07:00
if ( value = = null )
{
return true ;
}
return ( value = = "True" ) ;
}
set
{
2018-04-04 10:11:57 -07:00
if ( this . HideExtruderOffsets ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . GcodeViewerHideExtruderOffsets , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( HideExtruderOffsets ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
public bool SyncToPrint
{
2018-04-18 14:38:09 -07:00
get = > UserSettings . Instance . get ( UserSettingsKey . LayerViewSyncToPrint ) = = "True" ;
2017-09-17 12:01:18 -07:00
set
{
2018-04-04 10:11:57 -07:00
if ( this . SyncToPrint ! = value )
{
2018-04-18 14:38:09 -07:00
UserSettings . Instance . set ( UserSettingsKey . LayerViewSyncToPrint , value . ToString ( ) ) ;
2018-04-04 10:11:57 -07:00
this . IsDirty = true ;
this . OnPropertyChanged ( nameof ( SyncToPrint ) ) ;
}
}
}
private bool _renderBuildVolume ;
public bool RenderBuildVolume
{
get = > _renderBuildVolume ;
set
{
if ( _renderBuildVolume ! = value )
{
_renderBuildVolume = value ;
this . OnPropertyChanged ( nameof ( RenderBuildVolume ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}
2018-04-02 14:55:54 -07:00
2018-04-04 10:11:57 -07:00
protected void OnPropertyChanged ( string name )
{
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( name ) ) ;
}
2017-09-17 12:01:18 -07:00
}
}