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-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
{
private TextWidget gcodeProcessingStateInfoText ;
2017-07-06 18:15:53 -07:00
internal GCode2DWidget gcode2DWidget ;
2017-06-16 18:04:47 -07:00
private PrintItemWrapper printItem = > ApplicationController . Instance . ActivePrintItem ;
2017-07-06 15:50:13 -07:00
2015-04-08 15:20:10 -07:00
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 ;
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 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 ;
2017-05-26 20:07:42 -07:00
private PartViewMode activeViewMode = PartViewMode . Layers3D ;
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-29 13:11:58 -07:00
private SystemWindow parentSystemWindow ;
2017-07-06 16:30:32 -07:00
public ViewGcodeBasic ( Vector3 viewerVolume , Vector2 bedCenter , BedShape bedShape , ViewControls3D viewControls3D )
2015-04-08 15:20:10 -07:00
{
2017-06-24 10:30:11 -07:00
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 . bedCenter = bedCenter ;
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 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 :
2017-07-06 16:24:25 -07:00
printer . BedPlate . ActiveLayerIndex + = 1 ;
2017-06-29 13:11:58 -07:00
break ;
case Keys . Down :
2017-07-06 16:24:25 -07:00
printer . BedPlate . ActiveLayerIndex - = 1 ;
2017-06-29 13:11:58 -07:00
break ;
}
}
}
2017-06-28 18:39:46 -07:00
private GCodeFile loadedGCode = > printer . BedPlate . LoadedGCode ;
2017-06-29 19:42:20 -07:00
internal 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 12:35:02 -07:00
gcode2DWidget = null ;
2015-04-08 15:20:10 -07:00
gcodeProcessingStateInfoText = null ;
2017-06-30 22:40:43 -07:00
var mainContainerTopToBottom = new FlowLayoutWidget ( FlowDirection . TopToBottom )
{
HAnchor = HAnchor . Max_FitToChildren_ParentWidth ,
VAnchor = VAnchor . Max_FitToChildren_ParentHeight
} ;
2015-04-08 15:20:10 -07:00
2017-02-01 16:39:24 -08:00
gcodeDisplayWidget = new GuiWidget ( )
{
HAnchor = HAnchor . ParentLeftRight ,
VAnchor = VAnchor . ParentBottomTop
} ;
2017-06-29 19:42:20 -07:00
2017-05-25 17:58:20 -07:00
if ( printItem ! = null )
{
2017-06-30 15:05:07 -07:00
SetProcessingMessage ( "Loading G-Code..." . Localize ( ) ) ;
bool isGCode = Path . GetExtension ( printItem . FileLocation ) . ToUpper ( ) = = ".GCODE" ;
string gcodeFilePath = isGCode ? printItem . FileLocation : printItem . GetGCodePathAndFileName ( ) ;
if ( File . Exists ( gcodeFilePath ) )
2017-05-25 17:58:20 -07:00
{
2017-06-30 22:26:25 -07:00
gcode2DWidget = new GCode2DWidget ( new Vector2 ( viewerVolume . x , viewerVolume . y ) , bedCenter )
2017-06-30 15:05:07 -07:00
{
Visible = ( activeViewMode = = PartViewMode . Layers2D )
} ;
gcodeDisplayWidget . AddChild ( gcode2DWidget ) ;
2017-05-25 17:58:20 -07:00
}
else
{
2017-06-30 15:05:07 -07:00
SetProcessingMessage ( string . Format ( "{0}\n'{1}'" , fileNotFoundMessage , printItem . Name ) ) ;
2017-05-25 17:58:20 -07:00
}
}
2017-06-24 08:32:09 -07:00
mainContainerTopToBottom . AddChild ( gcodeDisplayWidget ) ;
2015-04-08 15:20:10 -07:00
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
} ;
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-30 15:05:07 -07:00
2017-07-06 16:15:57 -07:00
// *************** AddGCodeFileControls ***************
2017-06-30 15:05:07 -07:00
SetProcessingMessage ( "" ) ;
if ( gcode2DWidget ! = null
& & loadedGCode = = null )
{
// 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.
if ( File . Exists ( printItem . FileLocation ) )
{
SetProcessingMessage ( string . Format ( fileTooBigToLoad , printItem . Name ) ) ;
}
else
{
SetProcessingMessage ( string . Format ( "{0}\n'{1}'" , fileNotFoundMessage , Path . GetFileName ( printItem . FileLocation ) ) ) ;
}
}
2017-06-30 22:26:25 -07:00
if ( loadedGCode ? . LineCount > 0 )
2017-06-30 15:05:07 -07:00
{
2017-06-30 22:26:25 -07:00
gradientWidget = new ColorGradientWidget ( loadedGCode )
{
Margin = new BorderDouble ( top : 55 , left : 11 ) ,
HAnchor = HAnchor . FitToChildren | HAnchor . ParentLeft ,
VAnchor = VAnchor . ParentTop ,
2017-07-06 16:24:25 -07:00
Visible = printer . BedPlate . RendererOptions . RenderSpeeds
2017-06-30 22:26:25 -07:00
} ;
2017-06-30 15:05:07 -07:00
AddChild ( gradientWidget ) ;
GCodeRenderer . ExtrusionColor = ActiveTheme . Instance . PrimaryAccentColor ;
2017-07-06 16:15:57 -07:00
var gcodeDetails = new GCodeDetails ( this . loadedGCode ) ;
2017-06-30 15:05:07 -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
} ) ;
}
}
2015-04-08 15:20:10 -07:00
2017-06-30 22:26:25 -07:00
internal 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 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-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 ;
}
2015-04-08 15:20:10 -07:00
base . OnClosed ( e ) ;
}
}
2016-06-27 12:05:14 -07:00
}