2014-02-15 18:06:03 -08:00
/ *
Copyright ( c ) 2014 , Lars Brubaker
All rights reserved .
Redistribution and use in source and binary forms , with or without
2015-04-08 15:20:10 -07:00
modification , are permitted provided that the following conditions are met :
2014-02-15 18:06:03 -08:00
1. Redistributions of source code must retain the above copyright notice , this
2015-04-08 15:20:10 -07:00
list of conditions and the following disclaimer .
2014-02-15 18:06:03 -08:00
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
2015-04-08 15:20:10 -07:00
and / or other materials provided with the distribution .
2014-02-15 18:06:03 -08:00
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
2015-04-08 15:20:10 -07:00
of the authors and should not be interpreted as representing official policies ,
2014-02-15 18:06:03 -08:00
either expressed or implied , of the FreeBSD Project .
* /
2014-01-29 19:09:30 -08:00
using MatterHackers.Agg ;
2015-04-08 15:20:10 -07:00
using MatterHackers.Agg.PlatformAbstract ;
2014-01-29 19:09:30 -08:00
using MatterHackers.Agg.UI ;
2014-02-04 13:30:42 -08:00
using MatterHackers.Localizations ;
2014-06-06 16:05:18 -07:00
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling ;
2015-04-08 15:20:10 -07:00
using MatterHackers.MatterControl.ContactForm ;
using MatterHackers.MatterControl.DataStorage ;
2016-02-04 09:50:00 -08:00
using MatterHackers.MatterControl.PrinterCommunication ;
2015-04-08 15:20:10 -07:00
using MatterHackers.VectorMath ;
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
2015-11-30 16:19:32 -08:00
using System.Linq ;
2015-04-08 15:20:10 -07:00
using System.Text ;
2014-01-29 19:09:30 -08:00
2014-02-15 18:06:03 -08:00
namespace MatterHackers.MatterControl.SlicerConfiguration
2014-01-29 19:09:30 -08:00
{
2015-04-08 15:20:10 -07:00
public class SettingsLayer
{
//Container class representing a collection of setting along with the meta info for that collection
public Dictionary < string , DataStorage . SliceSetting > settingsDictionary ;
public DataStorage . SliceSettingsCollection settingsCollectionData ;
public SettingsLayer ( DataStorage . SliceSettingsCollection settingsCollection , Dictionary < string , DataStorage . SliceSetting > settingsDictionary )
{
this . settingsCollectionData = settingsCollection ;
this . settingsDictionary = settingsDictionary ;
}
}
public class ActiveSliceSettings
{
private static ActiveSliceSettings globalInstance = null ;
private static string configFileExtension = "slice" ;
private List < SettingsLayer > activeSettingsLayers ;
public RootedObjectEventHandler CommitStatusChanged = new RootedObjectEventHandler ( ) ;
public RootedObjectEventHandler SettingsChanged = new RootedObjectEventHandler ( ) ;
private int settingsHashCode ;
private bool hasUncommittedChanges = false ;
public bool HasUncommittedChanges
{
get
{
return hasUncommittedChanges ;
}
set
{
if ( this . hasUncommittedChanges ! = value )
{
this . hasUncommittedChanges = value ;
OnCommitStatusChanged ( ) ;
}
}
}
private void OnCommitStatusChanged ( )
{
CommitStatusChanged . CallEvents ( this , null ) ;
}
private void OnSettingsChanged ( )
{
//Set hash code back to 0
this . settingsHashCode = 0 ;
SettingsChanged . CallEvents ( this , null ) ;
}
// private so that it can only be gotten through the Instance
private ActiveSliceSettings ( )
{
}
public static ActiveSliceSettings Instance
{
get
{
if ( globalInstance = = null )
{
globalInstance = new ActiveSliceSettings ( ) ;
globalInstance . LoadAllSettings ( ) ;
}
return globalInstance ;
}
}
public void LoadAllSettings ( )
{
this . activeSettingsLayers = new List < SettingsLayer > ( ) ;
globalInstance . LoadSettingsForPrinter ( ) ;
//Ordering matters - Material presets trump Quality
globalInstance . LoadSettingsForQuality ( ) ;
globalInstance . LoadSettingsForMaterial ( 1 ) ;
if ( ActivePrinterProfile . Instance . ActivePrinter ! = null )
{
PrintLevelingData levelingData = PrintLevelingData . GetForPrinter ( ActivePrinterProfile . Instance . ActivePrinter ) ;
PrintLevelingPlane . Instance . SetPrintLevelingEquation (
2015-08-01 14:44:53 -07:00
levelingData . SampledPosition0 ,
levelingData . SampledPosition1 ,
levelingData . SampledPosition2 ,
2015-04-08 15:20:10 -07:00
ActiveSliceSettings . Instance . PrintCenter ) ;
}
OnSettingsChanged ( ) ;
this . HasUncommittedChanges = false ;
}
2015-06-17 15:42:08 -07:00
public void LoadSettingsForMaterial ( int extruderNumber1Based )
2015-04-08 15:20:10 -07:00
{
if ( ActivePrinterProfile . Instance . ActivePrinter ! = null )
{
SettingsLayer printerSettingsLayer ;
DataStorage . SliceSettingsCollection collection ;
2015-06-17 15:42:08 -07:00
if ( ActivePrinterProfile . Instance . GetMaterialSetting ( extruderNumber1Based ) ! = 0 )
2015-04-08 15:20:10 -07:00
{
2015-06-17 15:42:08 -07:00
int materialOneSettingsID = ActivePrinterProfile . Instance . GetMaterialSetting ( extruderNumber1Based ) ;
2015-04-08 15:20:10 -07:00
collection = DataStorage . Datastore . Instance . dbSQLite . Table < DataStorage . SliceSettingsCollection > ( ) . Where ( v = > v . Id = = materialOneSettingsID ) . Take ( 1 ) . FirstOrDefault ( ) ;
printerSettingsLayer = LoadConfigurationSettingsFromDatastore ( collection ) ;
}
else
{
printerSettingsLayer = new SettingsLayer ( new SliceSettingsCollection ( ) , new Dictionary < string , SliceSetting > ( ) ) ;
}
this . activeSettingsLayers . Add ( printerSettingsLayer ) ;
}
}
2015-06-17 15:42:08 -07:00
public string GetMaterialValue ( string sliceSetting , int extruderNumber1Based )
2015-04-08 15:20:10 -07:00
{
int numberOfActiveLayers = activeSettingsLayers . Count ;
string settingValue = null ;
2015-06-17 15:42:08 -07:00
if ( ActivePrinterProfile . Instance . GetMaterialSetting ( extruderNumber1Based ) ! = 0 )
2015-04-08 15:20:10 -07:00
{
2015-06-17 15:42:08 -07:00
int materialOneSettingsID = ActivePrinterProfile . Instance . GetMaterialSetting ( extruderNumber1Based ) ;
2015-04-08 15:20:10 -07:00
DataStorage . SliceSettingsCollection collection = DataStorage . Datastore . Instance . dbSQLite . Table < DataStorage . SliceSettingsCollection > ( ) . Where ( v = > v . Id = = materialOneSettingsID ) . Take ( 1 ) . FirstOrDefault ( ) ;
SettingsLayer printerSettingsLayer = LoadConfigurationSettingsFromDatastore ( collection ) ;
if ( printerSettingsLayer . settingsDictionary . ContainsKey ( sliceSetting ) )
{
settingValue = printerSettingsLayer . settingsDictionary [ sliceSetting ] . Value ;
}
}
if ( settingValue = = null )
{
//Go through settings layers one-by-one, starting with quality (index = 2), in reverse order, until we find a layer that contains the value
int startingLayer = Math . Min ( numberOfActiveLayers - 1 , 2 ) ;
for ( int i = startingLayer ; i > = 0 ; i - - )
{
if ( activeSettingsLayers [ i ] . settingsDictionary . ContainsKey ( sliceSetting ) )
{
settingValue = activeSettingsLayers [ i ] . settingsDictionary [ sliceSetting ] . Value ;
return settingValue ;
}
}
}
if ( settingValue = = null )
{
settingValue = "Unknown" ;
}
return settingValue ;
}
public void LoadSettingsForQuality ( )
{
if ( ActivePrinterProfile . Instance . ActivePrinter ! = null )
{
SettingsLayer printerSettingsLayer ;
DataStorage . SliceSettingsCollection collection ;
if ( ActivePrinterProfile . Instance . ActiveQualitySettingsID ! = 0 )
{
int materialOneSettingsID = ActivePrinterProfile . Instance . ActiveQualitySettingsID ;
collection = DataStorage . Datastore . Instance . dbSQLite . Table < DataStorage . SliceSettingsCollection > ( ) . Where ( v = > v . Id = = materialOneSettingsID ) . Take ( 1 ) . FirstOrDefault ( ) ;
printerSettingsLayer = LoadConfigurationSettingsFromDatastore ( collection ) ;
}
else
{
printerSettingsLayer = new SettingsLayer ( new SliceSettingsCollection ( ) , new Dictionary < string , SliceSetting > ( ) ) ;
}
this . activeSettingsLayers . Add ( printerSettingsLayer ) ;
}
}
public void LoadSettingsForPrinter ( )
{
//Load default settings from the .ini file as first layer
LoadDefaultConfigrationSettings ( ) ;
//Load printer settings from database as second layer
LoadPrinterConfigurationSettings ( ) ;
}
2014-04-08 19:33:09 -07:00
2015-01-23 08:03:59 -08:00
public bool HasFan ( )
{
return GetActiveValue ( "has_fan" ) = = "1" ;
}
2015-05-22 11:11:32 -07:00
public bool CenterOnBed ( )
{
return GetActiveValue ( "center_part_on_bed" ) = = "1" ;
}
2015-04-08 15:20:10 -07:00
public bool ShowResetConnection ( )
{
return GetActiveValue ( "show_reset_connection" ) = = "1" ;
}
2015-02-25 16:14:32 -08:00
2015-01-23 08:03:59 -08:00
public bool HasHardwareLeveling ( )
{
return GetActiveValue ( "has_hardware_leveling" ) = = "1" ;
}
2014-06-19 11:25:28 -07:00
2015-01-23 08:03:59 -08:00
public bool HasSdCardReader ( )
2015-04-08 15:20:10 -07:00
{
return GetActiveValue ( "has_sd_card_reader" ) = = "1" ;
}
2014-06-19 11:25:28 -07:00
2014-08-19 18:10:38 -07:00
public bool IsMakerbotGCodeFlavor ( )
{
return GetActiveValue ( "gcode_flavor" ) = = "makerbot" ;
}
2015-02-16 16:16:06 -08:00
public double BedTemperature
{
2015-04-08 15:20:10 -07:00
get
2015-02-16 16:16:06 -08:00
{
double targetTemp = 0 ;
if ( HasHeatedBed ( ) )
{
double . TryParse ( ActiveSliceSettings . Instance . GetActiveValue ( "bed_temperature" ) , out targetTemp ) ;
}
return targetTemp ;
}
}
2015-04-23 20:19:00 -07:00
/// <summary>
/// Control the PS_ON pin via M80/81 if enabled in firmware and printer settings, allowing the printer board to toggle off the ATX power supply
/// </summary>
public bool HasPowerControl
{
get
{
return GetActiveValue ( "has_power_control" ) = = "1" ;
}
}
2015-04-08 15:20:10 -07:00
public bool HasHeatedBed ( )
{
return GetActiveValue ( "has_heated_bed" ) = = "1" ;
}
2014-02-05 12:04:05 -08:00
2015-04-08 15:20:10 -07:00
public bool SupportEnabled
{
get
{
return GetActiveValue ( "support_material" ) = = "1" ;
}
}
public int SupportExtruder
{
get
{
return int . Parse ( GetActiveValue ( "support_material_extruder" ) ) ;
}
}
2014-02-05 12:04:05 -08:00
2015-11-30 16:19:32 -08:00
public int [ ] LayerToPauseOn
{
get
{
string [ ] userValues = GetActiveValue ( "layer_to_pause" ) . Split ( ';' ) ;
int temp ;
2015-12-29 12:57:24 -08:00
return userValues . Where ( v = > int . TryParse ( v , out temp ) ) . Select ( v = >
{
//Convert from 0 based index to 1 based index
int val = int . Parse ( v ) ;
// Special case for user entered zero that pushes 0 to 1, otherwise val = val - 1 for 1 based index
return val = = 0 ? 1 : val - 1 ;
} ) . ToArray ( ) ;
2015-11-30 16:19:32 -08:00
}
}
2015-08-03 15:48:36 -07:00
public double ProbePaperWidth
{
get
{
2015-08-04 11:34:02 -07:00
return double . Parse ( GetActiveValue ( "manual_probe_paper_width" ) ) ;
2015-08-03 15:48:36 -07:00
}
}
2015-04-08 15:20:10 -07:00
public bool RaftEnabled
{
get
{
return GetActiveValue ( "create_raft" ) = = "1" ;
}
}
public int RaftExtruder
{
get
{
return int . Parse ( GetActiveValue ( "raft_extruder" ) ) ;
}
}
public Dictionary < string , DataStorage . SliceSetting > DefaultSettings
{
get
{
return activeSettingsLayers [ 0 ] . settingsDictionary ;
}
}
public bool Contains ( string sliceSetting )
{
//Check whether the default settings (layer 0) contain a settings definition
return DefaultSettings . ContainsKey ( sliceSetting ) ;
}
public double MaxFanSpeed
{
get
{
return ParseDouble ( GetActiveValue ( "max_fan_speed" ) ) ;
}
}
public double FillDensity
{
get
{
string fillDensityValueString = GetActiveValue ( "fill_density" ) ;
if ( fillDensityValueString . Contains ( "%" ) )
{
string onlyNumber = fillDensityValueString . Replace ( "%" , "" ) ;
double ratio = ParseDouble ( onlyNumber ) / 100 ;
return ratio ;
}
else
{
return ParseDouble ( GetActiveValue ( "fill_density" ) ) ;
}
}
}
public double MinFanSpeed
{
get
{
return ParseDouble ( GetActiveValue ( "min_fan_speed" ) ) ;
}
}
public double FirstLayerHeight
{
get
{
string firstLayerValueString = GetActiveValue ( "first_layer_height" ) ;
if ( firstLayerValueString . Contains ( "%" ) )
{
string onlyNumber = firstLayerValueString . Replace ( "%" , "" ) ;
double ratio = ParseDouble ( onlyNumber ) / 100 ;
return LayerHeight * ratio ;
}
double firstLayerValue ;
firstLayerValue = ParseDouble ( firstLayerValueString ) ;
return firstLayerValue ;
}
}
public double FirstLayerExtrusionWidth
{
get
{
2015-06-09 11:30:14 -07:00
AsPercentOfReferenceOrDirect mapper = new AsPercentOfReferenceOrDirect ( "notused" , "first_layer_extrusion_width" , "nozzle_diameter" ) ;
2015-04-08 15:20:10 -07:00
double firstLayerValue ;
2015-06-09 11:30:14 -07:00
firstLayerValue = ParseDouble ( mapper . MappedValue ) ;
2015-04-08 15:20:10 -07:00
return firstLayerValue ;
}
}
private static double ParseDouble ( string firstLayerValueString )
{
double firstLayerValue ;
if ( ! double . TryParse ( firstLayerValueString , out firstLayerValue ) )
{
throw new Exception ( string . Format ( "Format cannot be parsed. FirstLayerHeight '{0}'" , firstLayerValueString ) ) ;
}
return firstLayerValue ;
}
public double LayerHeight
{
get { return ParseDouble ( GetActiveValue ( "layer_height" ) ) ; }
}
public Vector2 GetBedSize ( )
{
return BedSize ;
}
public Vector2 BedSize
{
get
{
return GetActiveVector2 ( "bed_size" ) ;
}
}
public MeshVisualizer . MeshViewerWidget . BedShape BedShape
{
get
{
switch ( GetActiveValue ( "bed_shape" ) )
{
case "rectangular" :
return MeshVisualizer . MeshViewerWidget . BedShape . Rectangular ;
case "circular" :
return MeshVisualizer . MeshViewerWidget . BedShape . Circular ;
default :
2014-02-24 22:18:46 -08:00
#if DEBUG
2015-04-08 15:20:10 -07:00
throw new NotImplementedException ( string . Format ( "'{0}' is not a known bed_shape." , GetActiveValue ( "bed_shape" ) ) ) ;
2014-02-24 22:18:46 -08:00
#else
return MeshVisualizer . MeshViewerWidget . BedShape . Rectangular ;
#endif
2015-04-08 15:20:10 -07:00
}
}
}
public Vector2 BedCenter
{
get
{
return GetActiveVector2 ( "print_center" ) ;
}
}
public double BuildHeight
{
get
{
return ParseDouble ( GetActiveValue ( "build_height" ) ) ;
}
}
public Vector2 PrintCenter
{
get
{
return GetActiveVector2 ( "print_center" ) ;
}
}
public int ExtruderCount
{
get
{
int extruderCount ;
string extruderCountString = ActiveSliceSettings . Instance . GetActiveValue ( "extruder_count" ) ;
if ( ! int . TryParse ( extruderCountString , out extruderCount ) )
{
return 1 ;
}
return extruderCount ;
}
}
public bool ExtrudersShareTemperature
{
get
{
return ( int . Parse ( ActiveSliceSettings . Instance . GetActiveValue ( "extruders_share_temperature" ) ) = = 1 ) ;
}
}
public Vector2 GetOffset ( int extruderIndex )
{
string currentOffsets = ActiveSliceSettings . Instance . GetActiveValue ( "extruder_offset" ) ;
string [ ] offsets = currentOffsets . Split ( ',' ) ;
int count = 0 ;
foreach ( string offset in offsets )
{
if ( count = = extruderIndex )
{
string [ ] xy = offset . Split ( 'x' ) ;
return new Vector2 ( double . Parse ( xy [ 0 ] ) , double . Parse ( xy [ 1 ] ) ) ;
}
count + + ;
}
return Vector2 . Zero ;
}
public double NozzleDiameter
{
get { return ParseDouble ( GetActiveValue ( "nozzle_diameter" ) ) ; }
}
public double FilamentDiameter
{
get { return ParseDouble ( GetActiveValue ( "filament_diameter" ) ) ; }
}
2016-01-16 21:33:11 -08:00
public bool LevelingRequiredToPrint
{
get
{
return GetActiveValue ( "print_leveling_required_to_print" ) = = "1" ;
}
}
2015-04-08 15:20:10 -07:00
///<summary>
///Returns the settings value at the 'top' of the stack
///</summary>
public string GetActiveValue ( string sliceSetting )
{
int numberOfActiveLayers = activeSettingsLayers . Count ;
//Go through settings layers one-by-one, in reverse order, until we find a layer that contains the value
for ( int i = numberOfActiveLayers - 1 ; i > = 0 ; i - - )
{
if ( activeSettingsLayers [ i ] . settingsDictionary . ContainsKey ( sliceSetting ) )
{
return activeSettingsLayers [ i ] . settingsDictionary [ sliceSetting ] . Value ;
}
}
return "Unknown" ;
}
/// <summary>
/// Returns whether or not the setting is overridden by the active layer
/// </summary>
/// AbsoluteBaseSettings = 0, EditableBaseSettings = 1, PresetOverrides... 2-n (examples: QualitySettings = 2, MaterialSettings = 3)
/// <param name="sliceSetting"></param>
/// <returns></returns>
public bool SettingExistsInLayer ( string sliceSetting , int layer )
{
bool settingExistsInLayer ;
int layerIndex = ( int ) layer ;
if ( layerIndex < activeSettingsLayers . Count )
{
settingExistsInLayer = ( activeSettingsLayers [ layerIndex ] . settingsDictionary . ContainsKey ( sliceSetting ) ) ;
}
else
{
settingExistsInLayer = false ;
}
return settingExistsInLayer ;
}
public Vector2 GetActiveVector2 ( string sliceSetting )
{
string [ ] twoValues = GetActiveValue ( sliceSetting ) . Split ( ',' ) ;
if ( twoValues . Length ! = 2 )
{
throw new Exception ( string . Format ( "Not parsing {0} as a Vector2" , sliceSetting ) ) ;
}
Vector2 valueAsVector2 = new Vector2 ( ) ;
valueAsVector2 . x = ParseDouble ( twoValues [ 0 ] ) ;
valueAsVector2 . y = ParseDouble ( twoValues [ 1 ] ) ;
return valueAsVector2 ;
}
public void LoadPrinterConfigurationSettings ( )
{
if ( ActivePrinterProfile . Instance . ActivePrinter ! = null )
{
DataStorage . SliceSettingsCollection collection ;
if ( ActivePrinterProfile . Instance . ActivePrinter . DefaultSettingsCollectionId ! = 0 )
{
int activePrinterSettingsID = ActivePrinterProfile . Instance . ActivePrinter . DefaultSettingsCollectionId ;
collection = DataStorage . Datastore . Instance . dbSQLite . Table < DataStorage . SliceSettingsCollection > ( ) . Where ( v = > v . Id = = activePrinterSettingsID ) . Take ( 1 ) . FirstOrDefault ( ) ;
}
else
{
collection = new DataStorage . SliceSettingsCollection ( ) ;
collection . Name = ActivePrinterProfile . Instance . ActivePrinter . Name ;
collection . Commit ( ) ;
ActivePrinterProfile . Instance . ActivePrinter . DefaultSettingsCollectionId = collection . Id ;
ActivePrinterProfile . Instance . ActivePrinter . Commit ( ) ;
}
SettingsLayer printerSettingsLayer = LoadConfigurationSettingsFromDatastore ( collection ) ;
this . activeSettingsLayers . Add ( printerSettingsLayer ) ;
}
}
private SettingsLayer LoadConfigurationSettingsFromDatastore ( DataStorage . SliceSettingsCollection collection )
{
Dictionary < string , DataStorage . SliceSetting > settingsDictionary = new Dictionary < string , DataStorage . SliceSetting > ( ) ;
IEnumerable < DataStorage . SliceSetting > settingsList = GetCollectionSettings ( collection . Id ) ;
foreach ( DataStorage . SliceSetting s in settingsList )
{
settingsDictionary [ s . Name ] = s ;
}
SettingsLayer settingsLayer = new SettingsLayer ( collection , settingsDictionary ) ;
return settingsLayer ;
}
private IEnumerable < DataStorage . SliceSetting > GetCollectionSettings ( int collectionId )
{
//Retrieve a list of saved printers from the Datastore
2014-01-29 19:09:30 -08:00
string query = string . Format ( "SELECT * FROM SliceSetting WHERE SettingsCollectionID = {0};" , collectionId ) ;
IEnumerable < DataStorage . SliceSetting > result = ( IEnumerable < DataStorage . SliceSetting > ) DataStorage . Datastore . Instance . dbSQLite . Query < DataStorage . SliceSetting > ( query ) ;
return result ;
2015-04-08 15:20:10 -07:00
}
2014-01-29 19:09:30 -08:00
2015-04-08 15:20:10 -07:00
private void LoadDefaultConfigrationSettings ( )
{
DataStorage . SliceSettingsCollection defaultCollection = new DataStorage . SliceSettingsCollection ( ) ;
defaultCollection . Name = "__default__" ;
SettingsLayer defaultSettingsLayer = LoadConfigurationSettingsFromFile ( Path . Combine ( "PrinterSettings" , "config.ini" ) , defaultCollection ) ;
this . activeSettingsLayers . Add ( defaultSettingsLayer ) ;
}
2014-01-29 19:09:30 -08:00
2015-06-11 12:06:40 -07:00
public void LoadSettingsFromIni ( )
2015-04-08 15:20:10 -07:00
{
OpenFileDialogParams openParams = new OpenFileDialogParams ( "Load Slice Configuration|*.slice;*.ini" ) ;
2014-01-29 19:09:30 -08:00
openParams . ActionButtonLabel = "Load Configuration" ;
openParams . Title = "MatterControl: Select A File" ;
2014-10-09 12:23:31 -07:00
FileDialog . OpenFileDialog ( openParams , onSettingsFileSelected ) ;
2015-04-08 15:20:10 -07:00
}
2014-01-29 19:09:30 -08:00
2015-04-08 15:20:10 -07:00
private void onSettingsFileSelected ( OpenFileDialogParams openParams )
2014-10-09 12:23:31 -07:00
{
if ( openParams . FileNames ! = null )
{
LoadConfigurationSettingsFromFileAsUnsaved ( openParams . FileName ) ;
ApplicationController . Instance . ReloadAdvancedControlsPanel ( ) ;
}
}
2015-04-08 15:20:10 -07:00
public SettingsLayer LoadConfigurationSettingsFromFile ( string pathAndFileName , DataStorage . SliceSettingsCollection collection )
{
Dictionary < string , DataStorage . SliceSetting > settingsDictionary = new Dictionary < string , DataStorage . SliceSetting > ( ) ;
SettingsLayer activeCollection ;
try
{
if ( StaticData . Instance . FileExists ( pathAndFileName ) )
{
foreach ( string line in StaticData . Instance . ReadAllLines ( pathAndFileName ) )
{
//Ignore commented lines
if ( ! line . StartsWith ( "#" ) )
{
string [ ] settingLine = line . Split ( '=' ) ;
string keyName = settingLine [ 0 ] . Trim ( ) ;
string settingDefaultValue = settingLine [ 1 ] . Trim ( ) ;
DataStorage . SliceSetting sliceSetting = new DataStorage . SliceSetting ( ) ;
sliceSetting . Name = keyName ;
sliceSetting . Value = settingDefaultValue ;
settingsDictionary . Add ( keyName , sliceSetting ) ;
}
}
activeCollection = new SettingsLayer ( collection , settingsDictionary ) ;
return activeCollection ;
}
return null ;
}
catch ( Exception e )
{
2015-09-11 10:48:24 -07:00
Debug . Print ( e . Message ) ;
2015-09-17 13:45:26 -07:00
GuiWidget . BreakInDebugger ( ) ;
2015-04-08 15:20:10 -07:00
Debug . WriteLine ( string . Format ( "Error loading configuration: {0}" , e ) ) ;
return null ;
}
}
public void LoadConfigurationSettingsFromFileAsUnsaved ( string pathAndFileName )
{
try
{
if ( File . Exists ( pathAndFileName ) )
{
string [ ] lines = System . IO . File . ReadAllLines ( pathAndFileName ) ;
foreach ( string line in lines )
{
//Ignore commented lines
if ( line . Trim ( ) ! = "" & & ! line . StartsWith ( "#" ) )
{
string [ ] settingLine = line . Split ( '=' ) ;
if ( settingLine . Length > 1 )
{
string keyName = settingLine [ 0 ] . Trim ( ) ;
string settingDefaultValue = settingLine [ 1 ] . Trim ( ) ;
//Add the setting to the active layer
SaveValue ( keyName , settingDefaultValue ) ;
}
}
}
}
}
catch ( Exception e )
{
2015-09-11 10:48:24 -07:00
Debug . Print ( e . Message ) ;
2015-09-17 13:45:26 -07:00
GuiWidget . BreakInDebugger ( ) ;
2015-04-08 15:20:10 -07:00
Debug . WriteLine ( string . Format ( "Error loading configuration: {0}" , e ) ) ;
}
}
public void SaveValue ( string keyName , string keyValue , int layerIndex = 1 )
{
SettingsLayer layer = this . activeSettingsLayers [ layerIndex ] ;
if ( layer . settingsDictionary . ContainsKey ( keyName )
& & layer . settingsDictionary [ keyName ] . Value ! = keyValue )
{
layer . settingsDictionary [ keyName ] . Value = keyValue ;
OnSettingsChanged ( ) ;
HasUncommittedChanges = true ;
}
else
{
DataStorage . SliceSetting sliceSetting = new DataStorage . SliceSetting ( ) ;
sliceSetting . Name = keyName ;
sliceSetting . Value = keyValue ;
sliceSetting . SettingsCollectionId = layer . settingsCollectionData . Id ;
layer . settingsDictionary [ keyName ] = sliceSetting ;
OnSettingsChanged ( ) ;
HasUncommittedChanges = true ;
}
}
public void CommitChanges ( )
{
for ( int i = 1 ; i < this . activeSettingsLayers . Count ; i + + )
{
CommitLayerChanges ( i ) ;
}
HasUncommittedChanges = false ;
}
public void CommitLayerChanges ( int layerIndex )
{
SettingsLayer layer = this . activeSettingsLayers [ layerIndex ] ;
foreach ( KeyValuePair < String , DataStorage . SliceSetting > item in layer . settingsDictionary )
{
item . Value . Commit ( ) ;
}
}
public void SaveAs ( )
{
SaveFileDialogParams saveParams = new SaveFileDialogParams ( "Save Slice Configuration" . Localize ( ) + "|*." + configFileExtension ) ;
2014-10-09 12:23:31 -07:00
saveParams . FileName = "default_settings.ini" ;
FileDialog . SaveFileDialog ( saveParams , onExportFileSelected ) ;
2015-04-08 15:20:10 -07:00
}
2014-01-29 19:09:30 -08:00
2015-04-08 15:20:10 -07:00
private void onExportFileSelected ( SaveFileDialogParams saveParams )
2014-10-09 12:23:31 -07:00
{
2016-02-12 10:26:40 -08:00
if ( ! string . IsNullOrEmpty ( saveParams . FileName ) )
2014-10-09 12:23:31 -07:00
{
GenerateConfigFile ( saveParams . FileName ) ;
}
2015-04-08 15:20:10 -07:00
}
2014-10-09 12:23:31 -07:00
2015-04-08 15:20:10 -07:00
public override int GetHashCode ( )
{
if ( this . settingsHashCode = = 0 )
{
// make a new dictionary so we only hash on the current values and keys.
StringBuilder bigStringForHashCode = new StringBuilder ( ) ;
foreach ( KeyValuePair < String , DataStorage . SliceSetting > setting in this . DefaultSettings )
{
string activeValue = GetActiveValue ( setting . Key ) ;
bigStringForHashCode . Append ( setting . Key ) ;
bigStringForHashCode . Append ( activeValue ) ;
}
this . settingsHashCode = bigStringForHashCode . ToString ( ) . GetHashCode ( ) ;
}
return this . settingsHashCode ;
2014-10-09 12:23:31 -07:00
}
2015-04-08 15:20:10 -07:00
public void GenerateConfigFile ( string fileName )
{
List < string > configFileAsList = new List < string > ( ) ;
foreach ( KeyValuePair < String , DataStorage . SliceSetting > setting in this . DefaultSettings )
{
string activeValue = GetActiveValue ( setting . Key ) ;
2015-05-20 13:36:29 -07:00
activeValue = GCodeProcessing . ReplaceMacroValues ( activeValue ) ;
2015-04-08 15:20:10 -07:00
string settingString = string . Format ( "{0} = {1}" , setting . Key , activeValue ) ;
configFileAsList . Add ( settingString ) ;
}
string configFileAsString = string . Join ( "\n" , configFileAsList . ToArray ( ) ) ;
2014-01-29 19:09:30 -08:00
2014-10-09 12:23:31 -07:00
//To do - add file extension if it doesn't exist
2015-04-08 15:20:10 -07:00
FileStream fs = new FileStream ( fileName , FileMode . Create ) ;
StreamWriter sw = new System . IO . StreamWriter ( fs ) ;
sw . Write ( configFileAsString ) ;
sw . Close ( ) ;
}
public bool IsValid ( )
{
try
{
if ( LayerHeight > NozzleDiameter )
{
string error = "'Layer Height' must be less than or equal to the 'Nozzle Diameter'." . Localize ( ) ;
string details = string . Format ( "Layer Height = {0}\nNozzle Diameter = {1}" . Localize ( ) , LayerHeight , NozzleDiameter ) ;
2015-06-09 11:30:14 -07:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'General' -> 'Layers/Surface'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
else if ( FirstLayerHeight > NozzleDiameter )
{
2016-02-09 15:05:03 -08:00
string error = "'First Layer Height' must be less than or equal to the 'Nozzle Diameter'." . Localize ( ) ;
2015-04-08 15:20:10 -07:00
string details = string . Format ( "First Layer Height = {0}\nNozzle Diameter = {1}" . Localize ( ) , FirstLayerHeight , NozzleDiameter ) ;
2015-06-09 11:30:14 -07:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'General' -> 'Layers/Surface'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
2016-02-04 09:50:00 -08:00
// If we have print leveling turned on then make sure we don't have any leveling commands in the start gcode.
if ( PrinterConnectionAndCommunication . Instance . ActivePrinter . DoPrintLeveling )
{
string [ ] startGCode = ActiveSliceSettings . Instance . GetActiveValue ( "start_gcode" ) . Replace ( "\\n" , "\n" ) . Split ( '\n' ) ;
foreach ( string startGCodeLine in startGCode )
{
if ( startGCodeLine . StartsWith ( "G29" ) )
{
string error = "Start G-Code cannot contain G29 if Print Leveling is enabled." . Localize ( ) ;
string details = "Your Start G-Code should not contain a G29 if you are planning on using print leveling. Change your start G-Code or turn off print leveling" . Localize ( ) ;
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Extrusion' -> 'First Layer'" . Localize ( ) ;
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
if ( startGCodeLine . StartsWith ( "G30" ) )
{
string error = "Start G-Code cannot contain G30 if Print Leveling is enabled." . Localize ( ) ;
string details = "Your Start G-Code should not contain a G30 if you are planning on using print leveling. Change your start G-Code or turn off print leveling" . Localize ( ) ;
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Extrusion' -> 'First Layer'" . Localize ( ) ;
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
}
}
2015-04-08 15:20:10 -07:00
if ( FirstLayerExtrusionWidth > NozzleDiameter * 4 )
{
2016-02-09 15:05:03 -08:00
string error = "'First Layer Extrusion Width' must be less than or equal to the 'Nozzle Diameter' * 4." . Localize ( ) ;
2015-04-08 15:20:10 -07:00
string details = string . Format ( "First Layer Extrusion Width = {0}\nNozzle Diameter = {1}" . Localize ( ) , GetActiveValue ( "first_layer_extrusion_width" ) , NozzleDiameter ) ;
2015-07-31 12:22:32 -07:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Extrusion' -> 'First Layer'" . Localize ( ) ;
2015-06-09 11:30:14 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
if ( FirstLayerExtrusionWidth < = 0 )
{
2016-02-09 15:05:03 -08:00
string error = "'First Layer Extrusion Width' must be greater than 0." . Localize ( ) ;
2015-06-09 11:30:14 -07:00
string details = string . Format ( "First Layer Extrusion Width = {0}" . Localize ( ) , GetActiveValue ( "first_layer_extrusion_width" ) ) ;
2015-07-31 12:22:32 -07:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Extrusion' -> 'First Layer'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
if ( MinFanSpeed > 100 )
{
2016-02-09 15:05:03 -08:00
string error = "The Minimum Fan Speed can only go as high as 100%." . Localize ( ) ;
2015-04-08 15:20:10 -07:00
string details = string . Format ( "It is currently set to {0}." . Localize ( ) , MinFanSpeed ) ;
2016-02-09 15:05:03 -08:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Cooling'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
if ( MaxFanSpeed > 100 )
{
2016-02-09 15:05:03 -08:00
string error = "The Maximum Fan Speed can only go as high as 100%." . Localize ( ) ;
2015-04-08 15:20:10 -07:00
string details = string . Format ( "It is currently set to {0}." . Localize ( ) , MaxFanSpeed ) ;
2016-02-09 15:05:03 -08:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Cooling'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
if ( ExtruderCount < 1 )
{
string error = "The Extruder Count must be at least 1." . Localize ( ) ;
string details = string . Format ( "It is currently set to {0}." . Localize ( ) , ExtruderCount ) ;
2016-02-09 15:05:03 -08:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'Printer' -> 'Features'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
if ( FillDensity < 0 | | FillDensity > 1 )
{
2016-02-09 15:05:03 -08:00
string error = "The Fill Density must be between 0 and 1." . Localize ( ) ;
2015-04-08 15:20:10 -07:00
string details = string . Format ( "It is currently set to {0}." . Localize ( ) , FillDensity ) ;
2015-06-09 11:30:14 -07:00
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'General' -> 'Infill'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return false ;
}
2015-10-20 15:39:59 -07:00
if ( FillDensity = = 1
& & GetActiveValue ( "infill_type" ) ! = "LINES" )
{
string error = "Solid Infill works best when set to LINES." . Localize ( ) ;
string details = string . Format ( "It is currently set to {0}." . Localize ( ) , GetActiveValue ( "infill_type" ) ) ;
string location = "Location: 'Settings & Controls' -> 'Settings' -> 'General' -> 'Infill Type'" . Localize ( ) ;
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2}" , error , details , location ) , "Slice Error" . Localize ( ) ) ;
return true ;
}
2015-06-09 11:30:14 -07:00
string normalSpeedLocation = "Location: 'Settings & Controls' -> 'Settings' -> 'General' -> 'Speed'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
// If the given speed is part of the current slice engine then check that it is greater than 0.
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "bridge_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "external_perimeter_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "first_layer_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "gap_fill_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "infill_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "perimeter_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "small_perimeter_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "solid_infill_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "support_material_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "top_solid_infill_speed" , normalSpeedLocation ) ) return false ;
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "travel_speed" , normalSpeedLocation ) ) return false ;
2015-06-09 11:30:14 -07:00
string retractSpeedLocation = "Location: 'Settings & Controls' -> 'Settings' -> 'Filament' -> 'Filament' -> 'Retraction'" . Localize ( ) ;
2015-04-08 15:20:10 -07:00
if ( ! ValidateGoodSpeedSettingGreaterThan0 ( "retract_speed" , retractSpeedLocation ) ) return false ;
}
catch ( Exception e )
{
2015-09-11 10:48:24 -07:00
Debug . Print ( e . Message ) ;
2015-09-17 13:45:26 -07:00
GuiWidget . BreakInDebugger ( ) ;
2015-04-08 15:20:10 -07:00
string stackTraceNoBackslashRs = e . StackTrace . Replace ( "\r" , "" ) ;
ContactFormWindow . Open ( "Parse Error while slicing" . Localize ( ) , e . Message + stackTraceNoBackslashRs ) ;
return false ;
}
return true ;
}
private bool ValidateGoodSpeedSettingGreaterThan0 ( string speedSetting , string speedLocation )
{
string actualSpeedValueString = GetActiveValue ( speedSetting ) ;
string speedValueString = actualSpeedValueString ;
if ( speedValueString . EndsWith ( "%" ) )
{
speedValueString = speedValueString . Substring ( 0 , speedValueString . Length - 1 ) ;
}
bool valueWasNumber = true ;
double speedToCheck ;
if ( ! double . TryParse ( speedValueString , out speedToCheck ) )
{
valueWasNumber = false ;
}
if ( ! valueWasNumber
| | ( ActivePrinterProfile . Instance . ActiveSliceEngine . MapContains ( speedSetting )
& & speedToCheck < = 0 ) )
{
OrganizerSettingsData data = SliceSettingsOrganizer . Instance . GetSettingsData ( speedSetting ) ;
if ( data ! = null )
{
string error = string . Format ( "The '{0}' must be greater than 0." . Localize ( ) , data . PresentationName ) ;
string details = string . Format ( "It is currently set to {0}." . Localize ( ) , actualSpeedValueString ) ;
StyledMessageBox . ShowMessageBox ( null , string . Format ( "{0}\n\n{1}\n\n{2} -> '{3}'" , error , details , speedLocation , data . PresentationName ) , "Slice Error" . Localize ( ) ) ;
}
return false ;
}
return true ;
}
}
}