2019-03-19 17:18:33 -07:00
/ *
Copyright ( c ) 2019 , 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 .
* /
2019-05-14 17:42:37 -07:00
using System ;
2021-04-08 11:26:24 -07:00
using System.Collections.Generic ;
2019-05-14 17:42:37 -07:00
using System.Threading.Tasks ;
2019-05-07 15:57:20 -07:00
using MatterHackers.Agg ;
2019-03-19 17:18:33 -07:00
using MatterHackers.Agg.UI ;
2019-05-14 17:42:37 -07:00
using MatterHackers.DataConverters3D ;
2019-03-19 17:18:33 -07:00
using MatterHackers.Localizations ;
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling ;
2019-05-14 17:42:37 -07:00
using MatterHackers.MatterControl.DesignTools ;
using MatterHackers.MatterControl.Library ;
2019-05-20 16:56:16 -07:00
using MatterHackers.MatterControl.PartPreviewWindow ;
2019-05-14 17:42:37 -07:00
using MatterHackers.MatterControl.PrinterCommunication ;
2019-03-21 09:36:58 -07:00
using MatterHackers.MatterControl.SlicerConfiguration ;
2019-05-14 17:42:37 -07:00
using MatterHackers.VectorMath ;
2019-03-26 11:48:29 -07:00
using static MatterHackers . MatterControl . ConfigurationPage . PrintLeveling . XyCalibrationWizard ;
2019-03-19 17:18:33 -07:00
namespace MatterHackers.MatterControl
{
public class XyCalibrationSelectPage : WizardPage
{
2019-05-17 10:17:45 -07:00
private readonly RadioButton coarseCalibration ;
private readonly RadioButton normalCalibration ;
private readonly RadioButton fineCalibration ;
2019-05-20 16:56:16 -07:00
private PartViewMode preCalibrationPrintViewMode ;
2019-03-19 17:18:33 -07:00
2019-03-26 11:50:52 -07:00
public XyCalibrationSelectPage ( XyCalibrationWizard calibrationWizard )
2019-03-26 11:48:29 -07:00
: base ( calibrationWizard )
2019-03-19 17:18:33 -07:00
{
this . WindowTitle = "Nozzle Offset Calibration Wizard" . Localize ( ) ;
2019-05-29 17:00:18 -07:00
this . HeaderText = "Calibration Print" . Localize ( ) ;
2019-03-19 17:18:33 -07:00
2019-05-20 16:56:16 -07:00
preCalibrationPrintViewMode = printer . ViewState . ViewMode ;
2019-03-19 17:18:33 -07:00
contentRow . Padding = theme . DefaultContainerPadding ;
2019-05-07 15:57:20 -07:00
2019-03-21 09:36:58 -07:00
// default to normal offset
2019-03-26 11:48:29 -07:00
calibrationWizard . Offset = printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) / 3.0 ;
2019-03-19 17:18:33 -07:00
2019-05-29 17:00:18 -07:00
contentRow . AddChild (
new TextWidget (
2019-05-29 17:51:28 -07:00
"This wizard will close to print a calibration part and resume after the print completes." . Localize ( ) ,
2019-05-29 17:00:18 -07:00
textColor : theme . TextColor ,
pointSize : theme . DefaultFontSize )
{
Margin = new BorderDouble ( bottom : theme . DefaultContainerPadding )
} ) ;
contentRow . AddChild (
new TextWidget (
"Calibration Mode" . Localize ( ) ,
textColor : theme . TextColor ,
pointSize : theme . DefaultFontSize )
{
Margin = new BorderDouble ( 0 , theme . DefaultContainerPadding )
} ) ;
2019-05-07 15:57:20 -07:00
var column = new FlowLayoutWidget ( FlowDirection . TopToBottom )
2019-03-19 17:18:33 -07:00
{
2019-05-07 15:57:20 -07:00
Margin = new BorderDouble ( left : theme . DefaultContainerPadding ) ,
2019-05-29 17:00:18 -07:00
HAnchor = HAnchor . Stretch ,
2019-05-07 15:57:20 -07:00
} ;
contentRow . AddChild ( column ) ;
2019-03-19 17:18:33 -07:00
2019-05-29 17:00:18 -07:00
var coarseText = calibrationWizard . Quality = = QualityType . Coarse ? "Initial (Recommended)" . Localize ( ) : "Coarse" . Localize ( ) ;
2019-05-10 15:57:48 -07:00
column . AddChild ( coarseCalibration = new RadioButton ( coarseText , textColor : theme . TextColor , fontSize : theme . DefaultFontSize )
2019-03-19 17:18:33 -07:00
{
2019-03-26 11:48:29 -07:00
Checked = calibrationWizard . Quality = = QualityType . Coarse
2019-03-19 17:18:33 -07:00
} ) ;
2019-03-20 16:06:07 -07:00
coarseCalibration . CheckedStateChanged + = ( s , e ) = >
{
2019-03-26 11:48:29 -07:00
calibrationWizard . Quality = QualityType . Coarse ;
calibrationWizard . Offset = printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) ;
2019-03-20 16:06:07 -07:00
} ;
2019-05-07 15:57:20 -07:00
2019-05-29 17:00:18 -07:00
var normalText = calibrationWizard . Quality = = QualityType . Normal ? "Normal (Recommended)" . Localize ( ) : "Normal" . Localize ( ) ;
2019-05-10 15:57:48 -07:00
column . AddChild ( normalCalibration = new RadioButton ( normalText , textColor : theme . TextColor , fontSize : theme . DefaultFontSize )
2019-03-19 17:18:33 -07:00
{
2019-03-26 11:48:29 -07:00
Checked = calibrationWizard . Quality = = QualityType . Normal
2019-03-19 17:18:33 -07:00
} ) ;
2019-03-20 16:06:07 -07:00
normalCalibration . CheckedStateChanged + = ( s , e ) = >
{
2019-03-26 11:48:29 -07:00
calibrationWizard . Quality = QualityType . Normal ;
calibrationWizard . Offset = printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) / 3.0 ;
2019-03-20 16:06:07 -07:00
} ;
2019-05-07 15:57:20 -07:00
column . AddChild ( fineCalibration = new RadioButton ( "Fine" . Localize ( ) , textColor : theme . TextColor , fontSize : theme . DefaultFontSize )
2019-03-19 17:18:33 -07:00
{
2019-03-26 11:48:29 -07:00
Checked = calibrationWizard . Quality = = QualityType . Fine
2019-03-19 17:18:33 -07:00
} ) ;
2019-03-20 16:06:07 -07:00
fineCalibration . CheckedStateChanged + = ( s , e ) = >
{
2019-03-26 11:48:29 -07:00
calibrationWizard . Quality = QualityType . Fine ;
calibrationWizard . Offset = printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) / 9.0 ;
2019-03-20 16:06:07 -07:00
} ;
2019-05-14 17:42:37 -07:00
2021-04-08 11:26:24 -07:00
var settingsContext = new SettingsContext ( printer , null , NamedSettingsLayers . All ) ;
int tabIndex = 0 ;
var allUiFields = new Dictionary < string , UIField > ( ) ;
var settingAdded = false ;
void AddSettingsRow ( string warning , string key )
{
if ( ! settingAdded )
{
contentRow . AddChild (
new TextWidget (
"Recommended Settings Changes" . Localize ( ) + ":" ,
textColor : theme . TextColor ,
pointSize : theme . DefaultFontSize )
{
Margin = new BorderDouble ( 10 , 0 , 0 , 20 )
} ) ;
settingAdded = true ;
}
contentRow . AddChild (
new WrappedTextWidget (
warning ,
textColor : theme . TextColor ,
pointSize : theme . DefaultFontSize )
{
Margin = new BorderDouble ( 0 , 10 , 0 , 20 )
} ) ;
var settingsData = PrinterSettings . SettingsData [ key ] ;
var row = SliceSettingsTabView . CreateItemRow ( settingsData , settingsContext , printer , theme , ref tabIndex , allUiFields ) ;
if ( row is SliceSettingsRow settingsRow )
{
settingsRow . ArrowDirection = ArrowDirection . Left ;
}
contentRow . AddChild ( row ) ;
}
if ( printer . Settings . GetValue < double > ( SettingsKey . layer_height ) < printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) / 2 )
{
// The layer height is very small and it will be hard to see features. Show a warning.
AddSettingsRow ( "The calibration object will printer better if the layer hight is set to a larger value. It is recommended that your increase it." . Localize ( ) , SettingsKey . layer_height ) ;
}
if ( printer . Settings . GetValue < bool > ( SettingsKey . create_raft ) )
{
// The layer height is very small and it will be hard to see features. Show a warning.
AddSettingsRow ( "A raft is not needed for the calibration object. It is recommended that you turn it off." . Localize ( ) , SettingsKey . create_raft ) ;
}
2019-05-14 17:42:37 -07:00
this . NextButton . Visible = false ;
2019-05-17 10:18:09 -07:00
// add in the option to tell the system the printer is already calibrated
var alreadyCalibratedButton = theme . CreateDialogButton ( "Already Calibrated" . Localize ( ) ) ;
alreadyCalibratedButton . Name = "Already Calibrated Button" ;
alreadyCalibratedButton . Click + = ( s , e ) = >
{
printer . Settings . SetValue ( SettingsKey . xy_offsets_have_been_calibrated , "1" ) ;
this . FinishWizard ( ) ;
} ;
this . AddPageAction ( alreadyCalibratedButton ) ;
2019-05-14 17:42:37 -07:00
var startCalibrationPrint = theme . CreateDialogButton ( "Start Print" . Localize ( ) ) ;
startCalibrationPrint . Name = "Start Calibration Print" ;
startCalibrationPrint . Click + = async ( s , e ) = >
{
await PrintCalibrationPart ( calibrationWizard ) ;
} ;
this . AcceptButton = startCalibrationPrint ;
this . AddPageAction ( startCalibrationPrint ) ;
}
private async Task PrintCalibrationPart ( XyCalibrationWizard calibrationWizard )
{
var scene = new Object3D ( ) ;
// create the calibration objects
IObject3D item = await CreateCalibrationObject ( printer , calibrationWizard ) ;
// add the calibration object to the bed
scene . Children . Add ( item ) ;
// move the part to the center of the bed
var bedBounds = printer . Settings . BedBounds ;
var aabb = item . GetAxisAlignedBoundingBox ( ) ;
item . Matrix * = Matrix4X4 . CreateTranslation ( bedBounds . Center . X - aabb . MinXYZ . X - aabb . XSize / 2 , bedBounds . Center . Y - aabb . MinXYZ . Y - aabb . YSize / 2 , - aabb . MinXYZ . Z ) ;
// register callbacks for print completion
printer . Connection . Disposed + = this . Connection_Disposed ;
2021-02-09 16:54:31 -08:00
printer . Connection . CancelCompleted + = this . Connection_PrintCanceled ;
2019-05-14 17:42:37 -07:00
printer . Connection . CommunicationStateChanged + = this . Connection_CommunicationStateChanged ;
// hide this window
this . DialogWindow . Visible = false ;
string gcodePath = EditContext . GCodeFilePath ( printer , scene ) ;
printer . Connection . CommunicationState = CommunicationStates . PreparingToPrint ;
( bool slicingSucceeded , string finalGCodePath ) = await ApplicationController . Instance . SliceItemLoadOutput (
printer ,
scene ,
gcodePath ) ;
// Only start print if slicing completed
if ( slicingSucceeded )
{
await printer . Bed . LoadContent ( new EditContext ( )
{
SourceItem = new FileSystemFileItem ( gcodePath ) ,
ContentStore = null // No content store for GCode
} ) ;
2021-06-24 10:36:32 -07:00
await printer . Connection . StartPrint ( finalGCodePath , printingMode : PrinterConnection . PrintingModes . Calibration ) ;
2019-05-14 17:42:37 -07:00
ApplicationController . Instance . MonitorPrintTask ( printer ) ;
}
else
{
printer . Connection . CommunicationState = CommunicationStates . Connected ;
}
}
private void Connection_PrintCanceled ( object sender , EventArgs e )
{
this . ReturnToCalibrationWizard ( ) ;
}
private void UnregisterPrinterEvents ( )
{
printer . Connection . Disposed - = this . Connection_Disposed ;
printer . Connection . CommunicationStateChanged - = this . Connection_CommunicationStateChanged ;
2021-02-09 16:54:31 -08:00
printer . Connection . CancelCompleted - = this . Connection_PrintCanceled ;
2019-05-14 17:42:37 -07:00
}
private void Connection_CommunicationStateChanged ( object sender , EventArgs e )
{
switch ( printer . Connection . CommunicationState )
{
case CommunicationStates . Disconnected :
case CommunicationStates . AttemptingToConnect :
case CommunicationStates . FailedToConnect :
case CommunicationStates . ConnectionLost :
case CommunicationStates . PrintingFromSd :
case CommunicationStates . FinishedPrint :
// We are no longer printing, exit and return to where we started
this . ReturnToCalibrationWizard ( ) ;
break ;
}
}
private void ReturnToCalibrationWizard ( )
{
UiThread . RunOnIdle ( ( ) = >
{
// Restore the original DialogWindow
this . DialogWindow . Visible = true ;
2019-05-17 17:19:11 -07:00
2019-05-20 16:56:16 -07:00
// Restore to original view mode
printer . ViewState . ViewMode = preCalibrationPrintViewMode ;
2019-05-17 17:19:11 -07:00
this . MoveToNextPage ( ) ;
2019-05-14 17:42:37 -07:00
} ) ;
this . UnregisterPrinterEvents ( ) ;
}
private void Connection_Disposed ( object sender , EventArgs e )
{
this . UnregisterPrinterEvents ( ) ;
}
private static async Task < IObject3D > CreateCalibrationObject ( PrinterConfig printer , XyCalibrationWizard calibrationWizard )
{
var layerHeight = printer . Settings . GetValue < double > ( SettingsKey . layer_height ) ;
2019-06-11 12:33:16 -07:00
var firstLayerHeight = printer . Settings . GetValue < double > ( SettingsKey . first_layer_height ) ;
2019-05-14 17:42:37 -07:00
switch ( calibrationWizard . Quality )
{
case QualityType . Coarse :
return await XyCalibrationTabObject3D . Create (
1 ,
2019-06-11 12:33:16 -07:00
Math . Max ( firstLayerHeight * 2 , layerHeight * 2 ) ,
2019-05-14 17:42:37 -07:00
calibrationWizard . Offset ,
2019-07-03 21:13:41 -07:00
printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) ,
printer . Settings . GetValue < double > ( SettingsKey . wipe_tower_size ) ) ;
2019-05-14 17:42:37 -07:00
default :
return await XyCalibrationFaceObject3D . Create (
1 ,
2019-06-11 12:33:16 -07:00
firstLayerHeight + layerHeight ,
2019-05-14 17:42:37 -07:00
layerHeight ,
calibrationWizard . Offset ,
printer . Settings . GetValue < double > ( SettingsKey . nozzle_diameter ) ,
printer . Settings . GetValue < double > ( SettingsKey . wipe_tower_size ) ,
2019-06-11 12:33:16 -07:00
4 ) ;
2019-05-14 17:42:37 -07:00
}
2019-03-19 17:18:33 -07:00
}
}
}