2014-01-29 19:09:30 -08:00
/ *
2017-05-24 19:11:51 -07:00
Copyright ( c ) 2017 , Lars Brubaker , John Lewin
2014-01-29 19:09:30 -08:00
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-01-29 19:09:30 -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-01-29 19:09:30 -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-01-29 19:09:30 -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-01-29 19:09:30 -08:00
either expressed or implied , of the FreeBSD Project .
* /
2017-05-24 19:11:51 -07:00
using System ;
using System.IO ;
2017-06-29 13:11:58 -07:00
using System.Linq ;
2017-06-30 16:09:31 -07:00
using System.Threading ;
2014-01-29 19:09:30 -08:00
using MatterHackers.Agg ;
2014-07-01 18:32:39 -07:00
using MatterHackers.Agg.UI ;
2015-04-08 15:20:10 -07:00
using MatterHackers.GCodeVisualizer ;
2014-02-04 13:30:42 -08:00
using MatterHackers.Localizations ;
2014-06-11 14:52:58 -07:00
using MatterHackers.MatterControl.PrinterCommunication ;
2014-04-15 18:13:27 -07:00
using MatterHackers.MatterControl.PrintQueue ;
using MatterHackers.MatterControl.SlicerConfiguration ;
2014-06-11 14:52:58 -07:00
using MatterHackers.MeshVisualizer ;
2014-04-15 18:13:27 -07:00
using MatterHackers.VectorMath ;
2014-01-29 19:09:30 -08:00
namespace MatterHackers.MatterControl.PartPreviewWindow
{
2017-06-24 13:17:43 -07:00
public class ViewGcodeBasic : GuiWidget
2015-04-08 15:20:10 -07:00
{
2017-06-24 13:17:43 -07:00
private MeshViewerWidget externalMeshViewer ;
2015-04-08 15:20:10 -07:00
public enum WindowMode { Embeded , StandAlone } ;
2017-05-25 17:58:20 -07:00
public SolidSlider selectLayerSlider ;
2015-04-08 15:20:10 -07:00
2017-05-25 17:58:20 -07:00
private SetLayerWidget setLayerWidget ;
private LayerNavigationWidget navigationWidget ;
public DoubleSolidSlider layerRenderRatioSlider ;
2015-04-08 15:20:10 -07:00
private TextWidget gcodeProcessingStateInfoText ;
2017-06-24 12:35:02 -07:00
private GCode2DWidget gcode2DWidget ;
2017-06-16 18:04:47 -07:00
private PrintItemWrapper printItem = > ApplicationController . Instance . ActivePrintItem ;
2015-04-08 15:20:10 -07:00
private bool startedSliceFromGenerateButton = false ;
private Button generateGCodeButton ;
private FlowLayoutWidget buttonBottomPanel ;
private FlowLayoutWidget layerSelectionButtonsPanel ;
private ViewControlsToggle viewControlsToggle ;
private GuiWidget gcodeDisplayWidget ;
2015-05-22 15:07:48 -07:00
private ColorGradientWidget gradientWidget ;
2015-04-13 11:04:17 -07:00
2015-04-08 15:20:10 -07:00
private EventHandler unregisterEvents ;
private WindowMode windowMode ;
2017-06-20 14:56:36 -07:00
private string partToStartLoadingOnFirstDraw = null ;
2015-04-08 15:20:10 -07:00
public delegate Vector2 GetSizeFunction ( ) ;
2017-06-24 13:17:43 -07:00
private string gcodeLoading = "Loading G-Code" . Localize ( ) ;
2017-03-01 13:48:49 -08:00
private string slicingErrorMessage = "Slicing Error.\nPlease review your slice settings." . Localize ( ) ;
private string pressGenerateMessage = "Press 'generate' to view layers" . Localize ( ) ;
private string fileNotFoundMessage = "File not found on disk." . Localize ( ) ;
private string fileTooBigToLoad = "GCode file too big to preview ({0})." . Localize ( ) ;
2015-04-08 15:20:10 -07:00
private Vector2 bedCenter ;
private Vector3 viewerVolume ;
2016-06-16 10:22:38 -07:00
private BedShape bedShape ;
2015-04-08 15:20:10 -07:00
private int sliderWidth ;
2017-05-26 20:07:42 -07:00
private PartViewMode activeViewMode = PartViewMode . Layers3D ;
2017-06-24 10:30:11 -07:00
private View3DConfig options ;
2017-06-19 09:17:57 -07:00
2017-06-24 10:30:11 -07:00
private PrinterConfig printer ;
2017-06-24 13:17:43 -07:00
private ViewControls3D viewControls3D ;
2017-06-24 08:32:09 -07:00
2017-06-28 20:48:00 -07:00
private BedConfig bedPlate ;
2017-06-29 13:11:58 -07:00
private SystemWindow parentSystemWindow ;
2017-06-24 13:17:43 -07:00
public ViewGcodeBasic ( Vector3 viewerVolume , Vector2 bedCenter , BedShape bedShape , WindowMode windowMode , ViewControls3D viewControls3D , ThemeConfig theme , MeshViewerWidget externalMeshViewer )
2015-04-08 15:20:10 -07:00
{
2017-06-24 13:17:43 -07:00
this . externalMeshViewer = externalMeshViewer ;
this . externalMeshViewer . TrackballTumbleWidget . DrawGlContent + = TrackballTumbleWidget_DrawGlContent ;
2017-06-24 10:30:11 -07:00
options = ApplicationController . Instance . Options . View3D ;
printer = ApplicationController . Instance . Printer ;
2017-06-19 09:17:57 -07:00
2017-06-24 13:17:43 -07:00
this . viewControls3D = viewControls3D ;
2015-04-08 15:20:10 -07:00
this . viewerVolume = viewerVolume ;
this . bedShape = bedShape ;
this . bedCenter = bedCenter ;
this . windowMode = windowMode ;
2017-02-16 14:00:21 -08:00
if ( UserSettings . Instance . IsTouchScreen )
2015-04-08 15:20:10 -07:00
{
sliderWidth = 20 ;
}
else
{
sliderWidth = 10 ;
}
2017-06-29 13:36:09 -07:00
RenderOpenGl . GLHelper . WireframeColor = ActiveTheme . Instance . PrimaryAccentColor ;
2015-06-11 12:06:40 -07:00
CreateAndAddChildren ( ) ;
2015-04-08 15:20:10 -07:00
2017-06-28 18:39:46 -07:00
ActiveSliceSettings . SettingChanged . RegisterEvent ( ( s , e ) = >
{
if ( e is StringEventArgs stringEvent )
2016-07-18 10:52:36 -07:00
{
2017-06-28 18:39:46 -07:00
if ( stringEvent . Data = = "extruder_offset" )
2017-06-28 18:16:26 -07:00
{
2017-06-28 18:39:46 -07:00
printer . BedPlate . GCodeRenderer . Clear3DGCode ( ) ;
2017-06-28 18:16:26 -07:00
}
2016-07-18 10:52:36 -07:00
}
2017-06-28 18:39:46 -07:00
} , ref unregisterEvents ) ;
2016-07-18 10:52:36 -07:00
2017-06-28 20:48:00 -07:00
bedPlate = ApplicationController . Instance . Printer . BedPlate ;
bedPlate . ActiveLayerChanged + = ActiveLayer_Changed ;
2017-06-28 18:39:46 -07:00
// TODO: Why do we clear GCode on AdvancedControlsPanelReloading - assume some slice settings should invalidate. If so, code should be more specific and bound to slice settings changed
ApplicationController . Instance . AdvancedControlsPanelReloading . RegisterEvent ( ( s , e ) = > printer . BedPlate . GCodeRenderer ? . Clear3DGCode ( ) , ref unregisterEvents ) ;
2017-03-15 16:17:06 -07:00
}
2017-06-29 13:11:58 -07:00
public override void OnLoad ( EventArgs args )
{
// Find and hook the parent system window KeyDown event
if ( this . Parents < SystemWindow > ( ) . FirstOrDefault ( ) is SystemWindow systemWindow )
{
systemWindow . KeyDown + = Parent_KeyDown ;
parentSystemWindow = systemWindow ;
}
base . OnLoad ( args ) ;
}
private void Parent_KeyDown ( object sender , KeyEventArgs keyEvent )
{
if ( this . Visible )
{
switch ( keyEvent . KeyCode )
{
case Keys . Up :
bedPlate . ActiveLayerIndex + = 1 ;
break ;
case Keys . Down :
bedPlate . ActiveLayerIndex - = 1 ;
break ;
}
}
}
2017-06-28 20:48:00 -07:00
private void ActiveLayer_Changed ( object sender , EventArgs e )
{
2017-06-29 13:11:58 -07:00
if ( selectLayerSlider ! = null
& & bedPlate . ActiveLayerIndex ! = ( int ) ( selectLayerSlider . Value + . 5 ) )
2017-06-28 20:48:00 -07:00
{
selectLayerSlider . Value = bedPlate . ActiveLayerIndex ;
}
}
2017-06-28 18:39:46 -07:00
private GCodeFile loadedGCode = > printer . BedPlate . LoadedGCode ;
2015-06-11 12:06:40 -07:00
private void CreateAndAddChildren ( )
2015-04-08 15:20:10 -07:00
{
2016-01-12 11:20:27 -08:00
CloseAllChildren ( ) ;
2017-06-02 06:45:04 -07:00
2017-06-24 10:28:33 -07:00
var buttonFactory = ApplicationController . Instance . Theme . BreadCrumbButtonFactory ;
2017-06-02 06:45:04 -07:00
2017-06-24 13:17:43 -07:00
externalMeshViewer = null ;
2017-06-24 12:35:02 -07:00
gcode2DWidget = null ;
2015-04-08 15:20:10 -07:00
gcodeProcessingStateInfoText = null ;
FlowLayoutWidget mainContainerTopToBottom = new FlowLayoutWidget ( FlowDirection . TopToBottom ) ;
2017-06-28 20:48:00 -07:00
mainContainerTopToBottom . HAnchor = HAnchor . Max_FitToChildren_ParentWidth ;
mainContainerTopToBottom . VAnchor = VAnchor . Max_FitToChildren_ParentHeight ;
2015-04-08 15:20:10 -07:00
buttonBottomPanel = new FlowLayoutWidget ( FlowDirection . LeftToRight ) ;
buttonBottomPanel . HAnchor = HAnchor . ParentLeftRight ;
buttonBottomPanel . Padding = new BorderDouble ( 3 , 3 ) ;
buttonBottomPanel . BackgroundColor = ActiveTheme . Instance . PrimaryBackgroundColor ;
2017-06-24 10:28:33 -07:00
generateGCodeButton = buttonFactory . Generate ( "Generate" . Localize ( ) ) ;
2016-03-03 16:57:43 -08:00
generateGCodeButton . Name = "Generate Gcode Button" ;
2017-05-24 19:11:51 -07:00
generateGCodeButton . Click + = ( s , e ) = >
{
UiThread . RunOnIdle ( ( ) = >
{
if ( ActiveSliceSettings . Instance . PrinterSelected )
{
2017-06-05 09:27:30 -07:00
// Save any pending changes before starting the print
ApplicationController . Instance . ActiveView3DWidget . PersistPlateIfNeeded ( ) . ContinueWith ( ( t ) = >
2017-05-24 19:11:51 -07:00
{
2017-06-05 09:27:30 -07:00
if ( ActiveSliceSettings . Instance . IsValid ( ) & & printItem ! = null )
{
generateGCodeButton . Visible = false ;
SlicingQueue . Instance . QueuePartForSlicing ( printItem ) ;
startedSliceFromGenerateButton = true ;
}
} ) ;
2017-05-24 19:11:51 -07:00
}
else
{
StyledMessageBox . ShowMessageBox ( null , "Oops! Please select a printer in order to continue slicing." , "Select Printer" , StyledMessageBox . MessageType . OK ) ;
}
} ) ;
} ;
2015-04-08 15:20:10 -07:00
buttonBottomPanel . AddChild ( generateGCodeButton ) ;
layerSelectionButtonsPanel = new FlowLayoutWidget ( FlowDirection . RightToLeft ) ;
layerSelectionButtonsPanel . HAnchor = HAnchor . ParentLeftRight ;
layerSelectionButtonsPanel . Padding = new BorderDouble ( 0 ) ;
GuiWidget holdPanelOpen = new GuiWidget ( 1 , generateGCodeButton . Height ) ;
layerSelectionButtonsPanel . AddChild ( holdPanelOpen ) ;
if ( windowMode = = WindowMode . StandAlone )
{
2017-06-24 10:28:33 -07:00
Button closeButton = buttonFactory . Generate ( "Close" . Localize ( ) ) ;
2015-04-08 15:20:10 -07:00
layerSelectionButtonsPanel . AddChild ( closeButton ) ;
closeButton . Click + = ( sender , e ) = >
{
CloseOnIdle ( ) ;
} ;
}
2017-02-01 16:39:24 -08:00
gcodeDisplayWidget = new GuiWidget ( )
{
HAnchor = HAnchor . ParentLeftRight ,
VAnchor = VAnchor . ParentBottomTop
} ;
2016-01-20 10:12:01 -08:00
string firstProcessingMessage = "Press 'Add' to select an item." . Localize ( ) ;
2017-05-25 17:58:20 -07:00
if ( printItem ! = null )
{
firstProcessingMessage = "Loading G-Code..." . Localize ( ) ;
if ( Path . GetExtension ( printItem . FileLocation ) . ToUpper ( ) = = ".GCODE" )
{
gcodeDisplayWidget . AddChild ( CreateGCodeViewWidget ( printItem . FileLocation ) ) ;
}
else
{
if ( File . Exists ( printItem . FileLocation ) )
{
string gcodePathAndFileName = printItem . GetGCodePathAndFileName ( ) ;
bool gcodeFileIsComplete = printItem . IsGCodeFileComplete ( gcodePathAndFileName ) ;
if ( printItem . SlicingHadError )
{
firstProcessingMessage = slicingErrorMessage ;
}
else
{
firstProcessingMessage = pressGenerateMessage ;
}
if ( File . Exists ( gcodePathAndFileName ) & & gcodeFileIsComplete )
{
gcodeDisplayWidget . AddChild ( CreateGCodeViewWidget ( gcodePathAndFileName ) ) ;
}
// we only hook these up to make sure we can regenerate the gcode when we want
printItem . SlicingOutputMessage + = sliceItem_SlicingOutputMessage ;
printItem . SlicingDone + = sliceItem_Done ;
}
else
{
firstProcessingMessage = string . Format ( "{0}\n'{1}'" , fileNotFoundMessage , printItem . Name ) ;
}
}
}
else
{
generateGCodeButton . Visible = false ;
}
2015-04-08 15:20:10 -07:00
SetProcessingMessage ( firstProcessingMessage ) ;
2017-06-24 08:32:09 -07:00
mainContainerTopToBottom . AddChild ( gcodeDisplayWidget ) ;
2015-04-08 15:20:10 -07:00
// add in a spacer
2017-02-01 16:39:24 -08:00
layerSelectionButtonsPanel . AddChild ( new GuiWidget ( )
{
HAnchor = HAnchor . ParentLeftRight
} ) ;
2015-04-08 15:20:10 -07:00
buttonBottomPanel . AddChild ( layerSelectionButtonsPanel ) ;
mainContainerTopToBottom . AddChild ( buttonBottomPanel ) ;
this . AddChild ( mainContainerTopToBottom ) ;
2015-11-09 12:36:47 -08:00
viewControls3D . ResetView + = ( sender , e ) = >
{
2017-05-26 21:28:35 -07:00
if ( gcodeDisplayWidget . Visible )
{
2017-06-24 12:35:02 -07:00
gcode2DWidget . CenterPartInView ( ) ;
2017-05-26 21:28:35 -07:00
}
2015-11-09 12:36:47 -08:00
} ;
2015-05-29 15:13:56 -07:00
viewControls3D . ActiveButton = ViewControls3DButtons . Rotate ;
2014-07-01 19:29:13 -07:00
2017-06-02 06:45:04 -07:00
viewControlsToggle = new ViewControlsToggle ( ApplicationController . Instance . Theme . ViewControlsButtonFactory , activeViewMode )
{
Visible = false ,
HAnchor = HAnchor . ParentRight
} ;
2017-06-24 12:24:40 -07:00
viewControlsToggle . ViewModeChanged + = ( s , e ) = >
{
// Respond to user driven view mode change events and store and switch to the new mode
activeViewMode = e . ViewMode ;
SwitchViewModes ( ) ;
} ;
2017-05-26 21:28:35 -07:00
viewControls3D . TransformStateChanged + = ( s , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-05-26 21:28:35 -07:00
switch ( e . TransformMode )
{
case ViewControls3DButtons . Translate :
2017-06-24 12:35:02 -07:00
if ( gcode2DWidget ! = null )
2017-05-27 17:48:32 -07:00
{
2017-06-24 12:35:02 -07:00
gcode2DWidget . TransformState = GCode2DWidget . ETransformState . Move ;
2017-05-27 17:48:32 -07:00
}
2017-05-26 21:28:35 -07:00
break ;
2017-06-24 13:17:43 -07:00
2017-05-26 21:28:35 -07:00
case ViewControls3DButtons . Scale :
2017-06-24 12:35:02 -07:00
if ( gcode2DWidget ! = null )
2017-05-27 17:48:32 -07:00
{
2017-06-24 12:35:02 -07:00
gcode2DWidget . TransformState = GCode2DWidget . ETransformState . Scale ;
2017-05-27 17:48:32 -07:00
}
2017-05-26 21:28:35 -07:00
break ;
}
2015-04-08 15:20:10 -07:00
} ;
2017-06-24 12:24:40 -07:00
this . AddChild ( viewControlsToggle ) ;
2015-04-08 15:20:10 -07:00
}
private RenderType GetRenderType ( )
{
2017-06-24 08:32:09 -07:00
var options = ApplicationController . Instance . Options . View3D ;
2015-04-08 15:20:10 -07:00
RenderType renderType = RenderType . Extrusions ;
2017-06-24 08:32:09 -07:00
if ( options . RenderMoves )
2015-04-08 15:20:10 -07:00
{
renderType | = RenderType . Moves ;
}
2017-06-24 08:32:09 -07:00
if ( options . RenderRetractions )
2015-04-08 15:20:10 -07:00
{
renderType | = RenderType . Retractions ;
}
2017-06-24 08:32:09 -07:00
if ( options . RenderSpeeds )
2015-04-08 15:20:10 -07:00
{
renderType | = RenderType . SpeedColors ;
}
2017-06-24 08:32:09 -07:00
if ( options . SimulateExtrusion )
2017-05-25 17:58:20 -07:00
{
renderType | = RenderType . SimulateExtrusion ;
}
2017-06-24 08:32:09 -07:00
if ( options . TransparentExtrusion )
2017-05-25 17:58:20 -07:00
{
renderType | = RenderType . TransparentExtrusion ;
}
2017-06-24 08:32:09 -07:00
if ( options . HideExtruderOffsets )
2015-04-08 15:20:10 -07:00
{
renderType | = RenderType . HideExtruderOffsets ;
}
return renderType ;
}
private void TrackballTumbleWidget_DrawGlContent ( object sender , EventArgs e )
{
2017-06-26 09:45:31 -07:00
if ( loadedGCode = = null | | printer . BedPlate . GCodeRenderer = = null | | ! this . Visible )
2017-05-26 15:40:48 -07:00
{
return ;
}
2017-06-28 20:48:00 -07:00
printer . BedPlate . RenderExtra ( ) ;
2015-04-08 15:20:10 -07:00
}
2017-05-25 17:58:20 -07:00
private void SetAnimationPosition ( )
{
2017-06-13 17:22:49 -07:00
int currentLayer = PrinterConnection . Instance . CurrentlyPrintingLayer ;
2017-05-25 17:58:20 -07:00
if ( currentLayer < = 0 )
{
selectLayerSlider . Value = 0 ;
layerRenderRatioSlider . SecondValue = 0 ;
layerRenderRatioSlider . FirstValue = 0 ;
}
else
{
selectLayerSlider . Value = currentLayer - 1 ;
2017-06-13 17:22:49 -07:00
layerRenderRatioSlider . SecondValue = PrinterConnection . Instance . RatioIntoCurrentLayer ;
2017-05-25 17:58:20 -07:00
layerRenderRatioSlider . FirstValue = 0 ;
}
}
2015-04-08 15:20:10 -07:00
2017-06-28 18:39:46 -07:00
private GCodeDetails gcodeDetails ;
2015-04-08 15:20:10 -07:00
2017-06-24 08:32:09 -07:00
internal GuiWidget ShowOverflowMenu ( )
2015-04-08 15:20:10 -07:00
{
2017-06-24 12:24:01 -07:00
var textColor = RGBA_Bytes . Black ;
2017-06-24 08:32:09 -07:00
var popupContainer = new FlowLayoutWidget ( FlowDirection . TopToBottom )
{
HAnchor = HAnchor . ParentLeftRight ,
Padding = 12 ,
BackgroundColor = RGBA_Bytes . White
} ;
2015-04-08 15:20:10 -07:00
// put in a show grid check box
2017-06-24 12:24:01 -07:00
CheckBox showGrid = new CheckBox ( "Print Bed" . Localize ( ) , textColor : textColor ) ;
2017-06-24 08:32:09 -07:00
showGrid . Checked = options . RenderGrid ;
showGrid . CheckedStateChanged + = ( sender , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-06-24 13:17:43 -07:00
// TODO: How (if at all) do we disable bed rendering on GCode2D?
2017-06-24 08:32:09 -07:00
options . RenderGrid = showGrid . Checked ;
} ;
popupContainer . AddChild ( showGrid ) ;
2015-04-08 15:20:10 -07:00
// put in a show moves checkbox
2017-06-24 12:24:01 -07:00
var showMoves = new CheckBox ( "Moves" . Localize ( ) , textColor : textColor ) ;
2017-06-24 08:32:09 -07:00
showMoves . Checked = options . RenderMoves ;
showMoves . CheckedStateChanged + = ( sender , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-06-24 08:32:09 -07:00
options . RenderMoves = showMoves . Checked ;
} ;
popupContainer . AddChild ( showMoves ) ;
2015-04-08 15:20:10 -07:00
// put in a show Retractions checkbox
2017-06-24 12:24:01 -07:00
CheckBox showRetractions = new CheckBox ( "Retractions" . Localize ( ) , textColor : textColor ) ;
2017-06-24 08:32:09 -07:00
showRetractions . Checked = options . RenderRetractions ;
showRetractions . CheckedStateChanged + = ( sender , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-06-24 08:32:09 -07:00
options . RenderRetractions = showRetractions . Checked ;
} ;
popupContainer . AddChild ( showRetractions ) ;
2015-04-08 15:20:10 -07:00
2017-06-29 13:11:58 -07:00
// Speeds checkbox
2017-06-24 12:24:01 -07:00
var showSpeeds = new CheckBox ( "Speeds" . Localize ( ) , textColor : textColor ) ;
2017-06-24 08:32:09 -07:00
showSpeeds . Checked = options . RenderSpeeds ;
showSpeeds . CheckedStateChanged + = ( sender , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-06-24 08:32:09 -07:00
gradientWidget . Visible = showSpeeds . Checked ;
options . RenderSpeeds = showSpeeds . Checked ;
} ;
2015-04-13 11:04:17 -07:00
2017-06-24 08:32:09 -07:00
popupContainer . AddChild ( showSpeeds ) ;
2015-04-08 15:20:10 -07:00
2017-06-29 13:11:58 -07:00
// Extrusion checkbox
2017-06-24 12:24:01 -07:00
var simulateExtrusion = new CheckBox ( "Extrusion" . Localize ( ) , textColor : textColor ) ;
2017-06-24 08:32:09 -07:00
simulateExtrusion . Checked = options . SimulateExtrusion ;
simulateExtrusion . CheckedStateChanged + = ( sender , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-06-24 08:32:09 -07:00
options . SimulateExtrusion = simulateExtrusion . Checked ;
} ;
popupContainer . AddChild ( simulateExtrusion ) ;
2015-04-08 15:20:10 -07:00
2017-06-29 13:11:58 -07:00
// Transparent checkbox
2017-06-24 12:24:01 -07:00
var transparentExtrusion = new CheckBox ( "Transparent" . Localize ( ) , textColor : textColor )
2017-05-25 17:58:20 -07:00
{
2017-06-24 08:32:09 -07:00
Checked = options . TransparentExtrusion ,
Margin = new BorderDouble ( 5 , 0 , 0 , 0 ) ,
HAnchor = HAnchor . ParentLeft ,
} ;
transparentExtrusion . CheckedStateChanged + = ( sender , e ) = >
{
options . TransparentExtrusion = transparentExtrusion . Checked ;
} ;
popupContainer . AddChild ( transparentExtrusion ) ;
2017-05-25 17:58:20 -07:00
2017-06-29 13:11:58 -07:00
// Extrusion checkbox
2017-05-25 17:58:20 -07:00
if ( ActiveSliceSettings . Instance . GetValue < int > ( SettingsKey . extruder_count ) > 1 )
2015-04-08 15:20:10 -07:00
{
2017-06-24 12:24:01 -07:00
CheckBox hideExtruderOffsets = new CheckBox ( "Hide Offsets" , textColor : textColor ) ;
2017-06-24 08:32:09 -07:00
hideExtruderOffsets . Checked = options . HideExtruderOffsets ;
2015-04-08 15:20:10 -07:00
hideExtruderOffsets . CheckedStateChanged + = ( sender , e ) = >
{
2017-06-24 08:32:09 -07:00
options . HideExtruderOffsets = hideExtruderOffsets . Checked ;
2015-04-08 15:20:10 -07:00
} ;
2017-06-24 08:32:09 -07:00
popupContainer . AddChild ( hideExtruderOffsets ) ;
2015-04-08 15:20:10 -07:00
}
2017-06-29 13:11:58 -07:00
// Sync To Print checkbox
2015-04-08 15:20:10 -07:00
if ( windowMode = = WindowMode . Embeded )
{
2017-06-24 12:24:01 -07:00
var syncToPrint = new CheckBox ( "Sync To Print" . Localize ( ) , textColor : textColor ) ;
2014-07-02 10:13:40 -07:00
syncToPrint . Checked = ( UserSettings . Instance . get ( "LayerViewSyncToPrint" ) = = "True" ) ;
2016-09-20 14:32:22 -07:00
syncToPrint . Name = "Sync To Print Checkbox" ;
2017-06-24 08:32:09 -07:00
syncToPrint . CheckedStateChanged + = ( s , e ) = >
2015-04-08 15:20:10 -07:00
{
2017-06-24 08:32:09 -07:00
options . SyncToPrint = syncToPrint . Checked ;
2015-04-08 15:20:10 -07:00
SetSyncToPrintVisibility ( ) ;
} ;
2017-06-24 08:32:09 -07:00
popupContainer . AddChild ( syncToPrint ) ;
2015-04-08 15:20:10 -07:00
// The idea here is we just got asked to rebuild the window (and it is being created now)
// because the gcode finished creating for the print that is printing.
// We don't want to be notified if any other updates happen to this gcode while it is printing.
2017-06-13 17:22:49 -07:00
if ( PrinterConnection . Instance . PrinterIsPrinting
2017-06-16 18:04:47 -07:00
& & ApplicationController . Instance . ActivePrintItem = = printItem )
2015-04-08 15:20:10 -07:00
{
2015-07-21 08:10:05 -07:00
printItem . SlicingOutputMessage - = sliceItem_SlicingOutputMessage ;
printItem . SlicingDone - = sliceItem_Done ;
2015-04-08 15:20:10 -07:00
generateGCodeButton . Visible = false ;
}
}
2017-06-24 08:32:09 -07:00
return popupContainer ;
2015-04-08 15:20:10 -07:00
}
2017-05-25 17:58:20 -07:00
private void SetSyncToPrintVisibility ( )
{
if ( windowMode = = WindowMode . Embeded )
{
2017-06-13 17:22:49 -07:00
bool printerIsRunningPrint = PrinterConnection . Instance . PrinterIsPaused | | PrinterConnection . Instance . PrinterIsPrinting ;
2017-05-25 17:58:20 -07:00
2017-06-24 08:32:09 -07:00
if ( options . SyncToPrint & & printerIsRunningPrint )
2017-05-25 17:58:20 -07:00
{
SetAnimationPosition ( ) ;
//navigationWidget.Visible = false;
//setLayerWidget.Visible = false;
layerRenderRatioSlider . Visible = false ;
selectLayerSlider . Visible = false ;
}
else
{
if ( layerRenderRatioSlider ! = null )
{
layerRenderRatioSlider . FirstValue = 0 ;
layerRenderRatioSlider . SecondValue = 1 ;
}
navigationWidget . Visible = true ;
setLayerWidget . Visible = true ;
layerRenderRatioSlider . Visible = true ;
selectLayerSlider . Visible = true ;
}
}
}
2015-04-08 15:20:10 -07:00
2017-05-26 20:07:42 -07:00
private void SwitchViewModes ( )
2014-07-01 19:29:13 -07:00
{
2017-05-26 20:07:42 -07:00
bool inLayers3DMode = activeViewMode = = PartViewMode . Layers3D ;
if ( inLayers3DMode )
2014-07-01 19:29:13 -07:00
{
2015-04-08 15:20:10 -07:00
UserSettings . Instance . set ( "LayerViewDefault" , "3D Layer" ) ;
2014-07-01 19:29:13 -07:00
}
else
{
2015-04-08 15:20:10 -07:00
UserSettings . Instance . set ( "LayerViewDefault" , "2D Layer" ) ;
2014-07-01 19:29:13 -07:00
2017-05-26 20:07:42 -07:00
// HACK: Getting the Layer2D view to show content only works if CenterPartInView is called after the control is visible and after some cycles have passed
2017-06-24 12:35:02 -07:00
UiThread . RunOnIdle ( gcode2DWidget . CenterPartInView ) ;
2014-07-01 19:29:13 -07:00
}
2017-05-26 20:07:42 -07:00
2017-06-24 12:35:02 -07:00
gcode2DWidget . Visible = ! inLayers3DMode ;
2014-07-01 19:29:13 -07:00
}
2015-04-08 15:20:10 -07:00
private void HookUpGCodeMessagesWhenDonePrinting ( object sender , EventArgs e )
{
2017-06-13 17:22:49 -07:00
if ( ! PrinterConnection . Instance . PrinterIsPaused & & ! PrinterConnection . Instance . PrinterIsPrinting )
2015-04-08 15:20:10 -07:00
{
// unregister first to make sure we don't double up in error (should not be needed but no harm)
2015-07-21 08:10:05 -07:00
printItem . SlicingOutputMessage - = sliceItem_SlicingOutputMessage ;
printItem . SlicingDone - = sliceItem_Done ;
2015-04-08 15:20:10 -07:00
// register for done slicing and slicing messages
2015-07-21 08:10:05 -07:00
printItem . SlicingOutputMessage + = sliceItem_SlicingOutputMessage ;
printItem . SlicingDone + = sliceItem_Done ;
2015-04-08 15:20:10 -07:00
generateGCodeButton . Visible = true ;
}
2017-05-25 17:58:20 -07:00
SetSyncToPrintVisibility ( ) ;
2015-04-08 15:20:10 -07:00
}
2017-06-30 16:09:31 -07:00
private void LoadProgress_Changed ( ( double progress0To1 , string processingState ) progress , CancellationTokenSource continueProcessing )
2017-06-20 14:56:36 -07:00
{
2017-06-30 16:09:31 -07:00
SetProcessingMessage ( string . Format ( "{0} {1:0}%..." , gcodeLoading , progress . progress0To1 * 100 ) ) ;
if ( this . HasBeenClosed )
{
continueProcessing . Cancel ( ) ;
}
2017-06-20 14:56:36 -07:00
}
2015-04-08 15:20:10 -07:00
private GuiWidget CreateGCodeViewWidget ( string pathAndFileName )
{
2017-06-24 12:35:02 -07:00
gcode2DWidget = new GCode2DWidget ( new Vector2 ( viewerVolume . x , viewerVolume . y ) , bedCenter , LoadProgress_Changed ) ;
gcode2DWidget . DoneLoading + = DoneLoadingGCode ;
gcode2DWidget . Visible = ( activeViewMode = = PartViewMode . Layers2D ) ;
2015-04-08 15:20:10 -07:00
partToStartLoadingOnFirstDraw = pathAndFileName ;
2017-06-24 12:35:02 -07:00
return gcode2DWidget ;
2015-04-08 15:20:10 -07:00
}
public override void OnDraw ( Graphics2D graphics2D )
{
2017-06-13 17:22:49 -07:00
bool printerIsRunningPrint = PrinterConnection . Instance . PrinterIsPaused | | PrinterConnection . Instance . PrinterIsPrinting ;
2017-06-24 08:32:09 -07:00
if ( options . SyncToPrint
2015-04-08 15:20:10 -07:00
& & printerIsRunningPrint )
{
2017-05-25 17:58:20 -07:00
SetAnimationPosition ( ) ;
2015-04-08 15:20:10 -07:00
}
if ( partToStartLoadingOnFirstDraw ! = null )
{
2017-06-24 12:35:02 -07:00
gcode2DWidget . LoadInBackground ( partToStartLoadingOnFirstDraw ) ;
2015-04-08 15:20:10 -07:00
partToStartLoadingOnFirstDraw = null ;
}
base . OnDraw ( graphics2D ) ;
}
private void SetProcessingMessage ( string message )
{
if ( gcodeProcessingStateInfoText = = null )
{
2017-06-20 14:56:36 -07:00
gcodeProcessingStateInfoText = new TextWidget ( message )
{
HAnchor = HAnchor . ParentCenter ,
VAnchor = VAnchor . ParentCenter ,
AutoExpandBoundsToText = true
} ;
2015-04-08 15:20:10 -07:00
2017-06-20 14:56:36 -07:00
var labelContainer = new GuiWidget ( ) ;
labelContainer . Selectable = false ;
2015-04-08 15:20:10 -07:00
labelContainer . AnchorAll ( ) ;
labelContainer . AddChild ( gcodeProcessingStateInfoText ) ;
gcodeDisplayWidget . AddChild ( labelContainer ) ;
}
if ( message = = "" )
{
2017-06-20 14:56:36 -07:00
gcodeProcessingStateInfoText . BackgroundColor = RGBA_Bytes . Transparent ;
2015-04-08 15:20:10 -07:00
}
else
{
gcodeProcessingStateInfoText . BackgroundColor = RGBA_Bytes . White ;
}
gcodeProcessingStateInfoText . Text = message ;
}
2017-06-28 19:49:31 -07:00
private void DoneLoadingGCode ( object sender , EventArgs e2 )
2015-04-08 15:20:10 -07:00
{
SetProcessingMessage ( "" ) ;
2017-06-24 12:35:02 -07:00
if ( gcode2DWidget ! = null
2017-06-24 10:30:11 -07:00
& & loadedGCode = = null )
2015-01-19 17:33:17 -08:00
{
2015-12-17 16:26:54 -08:00
// If we have finished loading the gcode and the source file exists but we don't have any loaded gcode it is because the loader decided to not load it.
2015-05-20 12:36:34 -07:00
if ( File . Exists ( printItem . FileLocation ) )
2015-01-19 17:33:17 -08:00
{
2015-02-21 16:30:29 -08:00
SetProcessingMessage ( string . Format ( fileTooBigToLoad , printItem . Name ) ) ;
2015-01-19 17:33:17 -08:00
}
else
{
SetProcessingMessage ( string . Format ( "{0}\n'{1}'" , fileNotFoundMessage , Path . GetFileName ( printItem . FileLocation ) ) ) ;
}
}
2017-06-28 20:48:00 -07:00
var printer = ApplicationController . Instance . Printer ;
2017-06-24 12:35:02 -07:00
if ( gcode2DWidget ! = null
2017-06-24 10:30:11 -07:00
& & loadedGCode ? . LineCount > 0 )
2015-04-08 15:20:10 -07:00
{
2017-06-20 14:56:36 -07:00
// TODO: Shouldn't we be clearing children from some known container and rebuilding?
gradientWidget ? . Close ( ) ;
2017-06-24 10:30:11 -07:00
gradientWidget = new ColorGradientWidget ( loadedGCode ) ;
2015-05-22 15:07:48 -07:00
AddChild ( gradientWidget ) ;
gradientWidget . Visible = false ;
2015-05-04 17:16:06 -07:00
2017-06-24 08:32:09 -07:00
gradientWidget . Visible = options . RenderSpeeds ;
2015-04-08 15:20:10 -07:00
viewControlsToggle . Visible = true ;
2017-06-20 14:56:36 -07:00
setLayerWidget ? . Close ( ) ;
2017-06-28 20:48:00 -07:00
setLayerWidget = new SetLayerWidget ( gcode2DWidget , ApplicationController . Instance . Theme . GCodeLayerButtons , ApplicationController . Instance . Printer . BedPlate ) ;
setLayerWidget . VAnchor = VAnchor . ParentTop ;
2015-04-08 15:20:10 -07:00
layerSelectionButtonsPanel . AddChild ( setLayerWidget ) ;
2017-06-20 14:56:36 -07:00
navigationWidget ? . Close ( ) ;
2017-06-24 12:35:02 -07:00
navigationWidget = new LayerNavigationWidget ( gcode2DWidget , ApplicationController . Instance . Theme . GCodeLayerButtons ) ;
2015-04-08 15:20:10 -07:00
navigationWidget . Margin = new BorderDouble ( 0 , 0 , 20 , 0 ) ;
layerSelectionButtonsPanel . AddChild ( navigationWidget ) ;
2017-06-20 14:56:36 -07:00
selectLayerSlider ? . Close ( ) ;
2017-06-29 13:35:44 -07:00
selectLayerSlider = new SolidSlider ( new Vector2 ( ) , sliderWidth , 0 , loadedGCode . LayerCount - 1 , Orientation . Vertical ) ;
2017-06-28 19:49:31 -07:00
selectLayerSlider . ValueChanged + = ( s , e ) = >
{
2017-06-28 20:48:00 -07:00
// TODO: Why would these need to be updated here as well as in assigned in the hslider below?
printer . BedPlate . RenderInfo . FeatureToStartOnRatio0To1 = layerRenderRatioSlider . FirstValue ;
printer . BedPlate . RenderInfo . FeatureToEndOnRatio0To1 = layerRenderRatioSlider . SecondValue ;
2017-06-28 19:49:31 -07:00
2017-06-28 20:48:00 -07:00
printer . BedPlate . ActiveLayerIndex = ( int ) ( selectLayerSlider . Value + . 5 ) ;
2017-06-28 19:49:31 -07:00
2017-06-28 20:48:00 -07:00
this . Invalidate ( ) ;
2017-06-28 19:49:31 -07:00
} ;
2017-06-28 20:48:00 -07:00
2015-04-08 15:20:10 -07:00
AddChild ( selectLayerSlider ) ;
2017-06-20 14:56:36 -07:00
layerRenderRatioSlider ? . Close ( ) ;
2017-05-25 17:58:20 -07:00
layerRenderRatioSlider = new DoubleSolidSlider ( new Vector2 ( ) , sliderWidth ) ;
2015-04-08 15:20:10 -07:00
layerRenderRatioSlider . FirstValue = 0 ;
2017-06-28 19:49:31 -07:00
layerRenderRatioSlider . FirstValueChanged + = ( s , e ) = >
{
2017-06-28 20:48:00 -07:00
printer . BedPlate . RenderInfo . FeatureToStartOnRatio0To1 = layerRenderRatioSlider . FirstValue ;
printer . BedPlate . RenderInfo . FeatureToEndOnRatio0To1 = layerRenderRatioSlider . SecondValue ;
this . Invalidate ( ) ;
2017-06-28 19:49:31 -07:00
} ;
2015-04-08 15:20:10 -07:00
layerRenderRatioSlider . SecondValue = 1 ;
2017-06-28 19:49:31 -07:00
layerRenderRatioSlider . SecondValueChanged + = ( s , e ) = >
{
2017-06-28 20:48:00 -07:00
printer . BedPlate . RenderInfo . FeatureToStartOnRatio0To1 = layerRenderRatioSlider . FirstValue ;
printer . BedPlate . RenderInfo . FeatureToEndOnRatio0To1 = layerRenderRatioSlider . SecondValue ;
this . Invalidate ( ) ;
2017-06-28 19:49:31 -07:00
} ;
2015-04-08 15:20:10 -07:00
AddChild ( layerRenderRatioSlider ) ;
SetSliderSizes ( ) ;
2017-06-28 20:48:00 -07:00
GCodeRenderer . ExtrusionColor = ActiveTheme . Instance . PrimaryAccentColor ;
// ResetRenderInfo
printer . BedPlate . RenderInfo = new GCodeRenderInfo (
0 ,
1 ,
Agg . Transform . Affine . NewIdentity ( ) ,
1 ,
GetRenderType ( ) ,
0 ,
1 ,
new Vector2 [ ]
{
ActiveSliceSettings . Instance . Helpers . ExtruderOffset ( 0 ) ,
ActiveSliceSettings . Instance . Helpers . ExtruderOffset ( 1 )
} ,
MeshViewerWidget . GetMaterialColor ) ;
2015-04-08 15:20:10 -07:00
2017-06-28 18:16:26 -07:00
this . gcodeDetails = new GCodeDetails ( this . loadedGCode ) ;
2017-06-28 18:39:46 -07:00
this . AddChild ( new GCodeDetailsView ( gcodeDetails )
{
Margin = new BorderDouble ( 0 , 0 , 35 , 5 ) ,
Padding = new BorderDouble ( 10 ) ,
BackgroundColor = new RGBA_Bytes ( 0 , 0 , 0 , ViewControlsBase . overlayAlpha ) ,
HAnchor = HAnchor . ParentRight | HAnchor . AbsolutePosition ,
VAnchor = VAnchor . ParentTop | VAnchor . FitToChildren ,
Width = 150
} ) ;
// TODO: Bad pattern - figure out how to revise
// However if the print finished or is canceled we are going to want to get updates again. So, hook the status event
PrinterConnection . Instance . CommunicationStateChanged . RegisterEvent ( HookUpGCodeMessagesWhenDonePrinting , ref unregisterEvents ) ;
UiThread . RunOnIdle ( SetSyncToPrintVisibility ) ;
2015-04-08 15:20:10 -07:00
2017-06-24 12:24:40 -07:00
// Switch to the most recent view mode, defaulting to Layers3D
SwitchViewModes ( ) ;
2015-05-22 15:07:48 -07:00
}
}
2015-05-04 17:16:06 -07:00
2017-06-28 19:49:31 -07:00
public override void OnBoundsChanged ( EventArgs e )
2015-04-08 15:20:10 -07:00
{
SetSliderSizes ( ) ;
2017-06-28 19:49:31 -07:00
base . OnBoundsChanged ( e ) ;
2015-04-08 15:20:10 -07:00
}
2017-05-25 17:58:20 -07:00
private void SetSliderSizes ( )
{
2017-06-29 14:09:47 -07:00
if ( selectLayerSlider = = null )
{
return ;
}
2017-05-25 17:58:20 -07:00
selectLayerSlider . OriginRelativeParent = new Vector2 ( gcodeDisplayWidget . Width - 20 , 70 ) ;
selectLayerSlider . TotalWidthInPixels = gcodeDisplayWidget . Height - 80 ;
layerRenderRatioSlider . OriginRelativeParent = new Vector2 ( 60 , 70 ) ;
layerRenderRatioSlider . TotalWidthInPixels = gcodeDisplayWidget . Width - 100 ;
}
2017-02-03 13:06:08 -08:00
public override void OnClosed ( ClosedEventArgs e )
2015-04-08 15:20:10 -07:00
{
2017-05-25 17:58:20 -07:00
unregisterEvents ? . Invoke ( this , null ) ;
2015-04-08 15:20:10 -07:00
2017-06-29 13:11:58 -07:00
// Find and unhook the parent system window KeyDown event
if ( parentSystemWindow ! = null )
{
parentSystemWindow . KeyDown - = Parent_KeyDown ;
}
2017-06-24 13:17:43 -07:00
if ( externalMeshViewer ! = null )
{
externalMeshViewer . TrackballTumbleWidget . DrawGlContent - = TrackballTumbleWidget_DrawGlContent ;
}
2015-04-08 15:20:10 -07:00
if ( printItem ! = null )
{
2015-07-21 08:10:05 -07:00
printItem . SlicingOutputMessage - = sliceItem_SlicingOutputMessage ;
printItem . SlicingDone - = sliceItem_Done ;
2015-04-08 15:20:10 -07:00
if ( startedSliceFromGenerateButton & & printItem . CurrentlySlicing )
{
SlicingQueue . Instance . CancelCurrentSlicing ( ) ;
}
}
base . OnClosed ( e ) ;
}
private void sliceItem_SlicingOutputMessage ( object sender , EventArgs e )
{
2017-06-28 19:49:31 -07:00
if ( e is StringEventArgs message & & message . Data ! = null )
2015-04-08 15:20:10 -07:00
{
SetProcessingMessage ( message . Data ) ;
}
else
{
SetProcessingMessage ( "" ) ;
}
}
private void sliceItem_Done ( object sender , EventArgs e )
{
// We can add this while we have it open (when we are done loading).
// So we need to make sure we only have it added once. This will be ok to run when
// not added or when added and will ensure we only have one hook.
2015-07-21 08:10:05 -07:00
printItem . SlicingOutputMessage - = sliceItem_SlicingOutputMessage ;
printItem . SlicingDone - = sliceItem_Done ;
2015-04-08 15:20:10 -07:00
2017-05-25 17:58:20 -07:00
UiThread . RunOnIdle ( CreateAndAddChildren ) ;
2015-04-08 15:20:10 -07:00
startedSliceFromGenerateButton = false ;
}
}
2016-06-27 12:05:14 -07:00
}