From 761b279a2b83ce9461e142eea4b60505006ec8aa Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 26 Feb 2012 15:37:29 +0100 Subject: [PATCH 1/6] Changes for new UI version --- build.sh | 9 +++++++-- scripts/win32/skeinforge.bat | 2 -- scripts/win32/skeinpypy.bat | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 scripts/win32/skeinforge.bat create mode 100644 scripts/win32/skeinpypy.bat diff --git a/build.sh b/build.sh index 358c743f..55086cb5 100755 --- a/build.sh +++ b/build.sh @@ -16,7 +16,7 @@ BUILD_TARGET=win32 ##Do we need to create the final archive ARCHIVE_FOR_DISTRIBUTION=1 ##Which version name are we appending to the final archive -BUILD_NAME=Alpha4 +BUILD_NAME=NewUI-Beta1 TARGET_DIR=${BUILD_TARGET}-SkeinPyPy-${BUILD_NAME} ##Which versions of external programs to use @@ -66,6 +66,9 @@ if [ $BUILD_TARGET = "win32" ]; then curl -L -O http://sourceforge.net/projects/pyserial/files/pyserial/${WIN_PYSERIAL_VERSION}/pyserial-${WIN_PYSERIAL_VERSION}.win32.exe/download mv download pyserial-${WIN_PYSERIAL_VERSION}.exe fi + if [ ! -f PyOpenGL-3.0.1.win32.exe ]; then + curl -L -O http://sourceforge.net/projects/pyopengl/files/PyOpenGL/3.0.1/PyOpenGL-3.0.1.win32.exe + fi #Get pypy if [ ! -f "pypy-${PYPY_VERSION}-win32.zip" ]; then curl -L -O https://bitbucket.org/pypy/pypy/downloads/pypy-${PYPY_VERSION}-win32.zip @@ -92,11 +95,13 @@ if [ $BUILD_TARGET = "win32" ]; then 7z x PortablePython_${WIN_PORTABLE_PY_VERSION}.exe \$_OUTDIR/App 7z x PortablePython_${WIN_PORTABLE_PY_VERSION}.exe \$_OUTDIR/Lib/site-packages 7z x pyserial-${WIN_PYSERIAL_VERSION}.exe PURELIB + 7z x PyOpenGL-3.0.1.win32.exe PURELIB mkdir -p ${TARGET_DIR}/python mv \$_OUTDIR/App/* ${TARGET_DIR}/python mv \$_OUTDIR/Lib/site-packages/wx* ${TARGET_DIR}/python/Lib/site-packages/ mv PURELIB/serial ${TARGET_DIR}/python/Lib + mv PURELIB/OpenGL ${TARGET_DIR}/python/Lib rm -rf \$_OUTDIR rm -rf PURELIB @@ -123,7 +128,7 @@ fi rm -rf ${TARGET_DIR}/pypy/lib-python/2.7/test #add Skeinforge -cp -a SkeinPyPy ${TARGET_DIR}/SkeinPyPy +cp -a SkeinPyPy_NewUI ${TARGET_DIR}/SkeinPyPy #Add the SSE2 check if we can build it, else we skip it. # If we don't have it SkeinPyPy will still function. But crash on machines that don't have SSE2 diff --git a/scripts/win32/skeinforge.bat b/scripts/win32/skeinforge.bat deleted file mode 100644 index 19b9e466..00000000 --- a/scripts/win32/skeinforge.bat +++ /dev/null @@ -1,2 +0,0 @@ -@python\python.exe SkeinPyPy\skeinforge_application\skeinforge.py - diff --git a/scripts/win32/skeinpypy.bat b/scripts/win32/skeinpypy.bat new file mode 100644 index 00000000..ef56c9ae --- /dev/null +++ b/scripts/win32/skeinpypy.bat @@ -0,0 +1 @@ +@python\python.exe SkeinPyPy\SkeinPyPy.py From 5921a7e947ddd2c68c50d99afc78612e6ad6c55d Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 27 Feb 2012 14:51:52 +0100 Subject: [PATCH 2/6] Split the main window code into a configBase and the main window Fixed first layer speed Fixed popup text update when warning/error is generated --- .../fabmetheus_utilities/settings.py | 385 +++++++++--------- SkeinPyPy_NewUI/newui/configWindowBase.py | 194 +++++++++ SkeinPyPy_NewUI/newui/mainWindow.py | 266 +++--------- SkeinPyPy_NewUI/newui/validators.py | 12 +- 4 files changed, 449 insertions(+), 408 deletions(-) create mode 100644 SkeinPyPy_NewUI/newui/configWindowBase.py diff --git a/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py b/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py index 3713501a..38de6477 100644 --- a/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py +++ b/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py @@ -13,7 +13,7 @@ import types, math from fabmetheus_utilities import archive -def defaultSetting(setting): +def DEFSET(setting): return setting.value def storedSetting(name): @@ -59,138 +59,143 @@ def calculateSolidLayerCount(setting): ret = int(math.ceil(solidThickness / layerHeight - 0.0001)) return ret +def firstLayerSpeedRatio(setting): + bottomSpeed = float(getSetting('bottom_layer_speed')) + speed = float(getSetting('print_speed')) + return bottomSpeed/speed + def getSkeinPyPyProfileInformation(): return { 'carve': { - 'Add_Layer_Template_to_SVG': defaultSetting, + 'Add_Layer_Template_to_SVG': DEFSET, 'Edge_Width_mm': calculateEdgeWidth, - 'Extra_Decimal_Places_float': defaultSetting, - 'Import_Coarseness_ratio': defaultSetting, + 'Extra_Decimal_Places_float': DEFSET, + 'Import_Coarseness_ratio': DEFSET, 'Layer_Height_mm': storedSetting("layer_height"), - 'Layers_From_index': defaultSetting, - 'Layers_To_index': defaultSetting, - 'Correct_Mesh': defaultSetting, - 'Unproven_Mesh': defaultSetting, - 'SVG_Viewer': defaultSetting, + 'Layers_From_index': DEFSET, + 'Layers_To_index': DEFSET, + 'Correct_Mesh': DEFSET, + 'Unproven_Mesh': DEFSET, + 'SVG_Viewer': DEFSET, },'scale': { 'Activate_Scale': "False", - 'XY_Plane_Scale_ratio': defaultSetting, - 'Z_Axis_Scale_ratio': defaultSetting, - 'SVG_Viewer': defaultSetting, + 'XY_Plane_Scale_ratio': DEFSET, + 'Z_Axis_Scale_ratio': DEFSET, + 'SVG_Viewer': DEFSET, },'bottom': { - 'Activate_Bottom': defaultSetting, - 'Additional_Height_over_Layer_Thickness_ratio': defaultSetting, - 'Altitude_mm': defaultSetting, - 'SVG_Viewer': defaultSetting, + 'Activate_Bottom': DEFSET, + 'Additional_Height_over_Layer_Thickness_ratio': DEFSET, + 'Altitude_mm': DEFSET, + 'SVG_Viewer': DEFSET, },'preface': { - 'Meta': defaultSetting, - 'Set_Positioning_to_Absolute': defaultSetting, - 'Set_Units_to_Millimeters': defaultSetting, - 'Start_at_Home': defaultSetting, - 'Turn_Extruder_Off_at_Shut_Down': defaultSetting, - 'Turn_Extruder_Off_at_Start_Up': defaultSetting, + 'Meta': DEFSET, + 'Set_Positioning_to_Absolute': DEFSET, + 'Set_Units_to_Millimeters': DEFSET, + 'Start_at_Home': DEFSET, + 'Turn_Extruder_Off_at_Shut_Down': DEFSET, + 'Turn_Extruder_Off_at_Start_Up': DEFSET, },'widen': { - 'Activate_Widen': defaultSetting, + 'Activate_Widen': DEFSET, },'inset': { - 'Add_Custom_Code_for_Temperature_Reading': defaultSetting, + 'Add_Custom_Code_for_Temperature_Reading': DEFSET, 'Infill_in_Direction_of_Bridge': "True", - 'Infill_Width_over_Thickness_ratio': defaultSetting, - 'Loop_Order_Choice': defaultSetting, - 'Overlap_Removal_Width_over_Perimeter_Width_ratio': defaultSetting, - 'Turn_Extruder_Heater_Off_at_Shut_Down': defaultSetting, - 'Volume_Fraction_ratio': defaultSetting, + 'Infill_Width_over_Thickness_ratio': DEFSET, + 'Loop_Order_Choice': DEFSET, + 'Overlap_Removal_Width_over_Perimeter_Width_ratio': DEFSET, + 'Turn_Extruder_Heater_Off_at_Shut_Down': DEFSET, + 'Volume_Fraction_ratio': DEFSET, },'fill': { 'Activate_Fill': "True", - 'Diaphragm_Period_layers': defaultSetting, - 'Diaphragm_Thickness_layers': defaultSetting, + 'Diaphragm_Period_layers': DEFSET, + 'Diaphragm_Thickness_layers': DEFSET, 'Extra_Shells_on_Alternating_Solid_Layer_layers': calculateShells, 'Extra_Shells_on_Base_layers': calculateShells, 'Extra_Shells_on_Sparse_Layer_layers': calculateShells, - 'Grid_Circle_Separation_over_Perimeter_Width_ratio': defaultSetting, - 'Grid_Extra_Overlap_ratio': defaultSetting, - 'Grid_Junction_Separation_Band_Height_layers': defaultSetting, - 'Grid_Junction_Separation_over_Octogon_Radius_At_End_ratio': defaultSetting, - 'Grid_Junction_Separation_over_Octogon_Radius_At_Middle_ratio': defaultSetting, - 'Infill_Begin_Rotation_degrees': defaultSetting, - 'Infill_Begin_Rotation_Repeat_layers': defaultSetting, - 'Infill_Odd_Layer_Extra_Rotation_degrees': defaultSetting, - 'Grid_Circular': defaultSetting, - 'Grid_Hexagonal': defaultSetting, - 'Grid_Rectangular': defaultSetting, - 'Line': defaultSetting, - 'Infill_Perimeter_Overlap_ratio': defaultSetting, + 'Grid_Circle_Separation_over_Perimeter_Width_ratio': DEFSET, + 'Grid_Extra_Overlap_ratio': DEFSET, + 'Grid_Junction_Separation_Band_Height_layers': DEFSET, + 'Grid_Junction_Separation_over_Octogon_Radius_At_End_ratio': DEFSET, + 'Grid_Junction_Separation_over_Octogon_Radius_At_Middle_ratio': DEFSET, + 'Infill_Begin_Rotation_degrees': DEFSET, + 'Infill_Begin_Rotation_Repeat_layers': DEFSET, + 'Infill_Odd_Layer_Extra_Rotation_degrees': DEFSET, + 'Grid_Circular': DEFSET, + 'Grid_Hexagonal': DEFSET, + 'Grid_Rectangular': DEFSET, + 'Line': DEFSET, + 'Infill_Perimeter_Overlap_ratio': DEFSET, 'Infill_Solidity_ratio': storedPercentSetting('fill_density'), 'Infill_Width': storedSetting("nozzle_size"), 'Solid_Surface_Thickness_layers': calculateSolidLayerCount, - 'Start_From_Choice': defaultSetting, - 'Surrounding_Angle_degrees': defaultSetting, - 'Thread_Sequence_Choice': defaultSetting, + 'Start_From_Choice': DEFSET, + 'Surrounding_Angle_degrees': DEFSET, + 'Thread_Sequence_Choice': DEFSET, },'multiply': { 'Activate_Multiply': "True", 'Center_X_mm': storedSetting("machine_center_x"), 'Center_Y_mm': storedSetting("machine_center_y"), 'Number_of_Columns_integer': "1", 'Number_of_Rows_integer': "1", - 'Reverse_Sequence_every_Odd_Layer': defaultSetting, - 'Separation_over_Perimeter_Width_ratio': defaultSetting, + 'Reverse_Sequence_every_Odd_Layer': DEFSET, + 'Separation_over_Perimeter_Width_ratio': DEFSET, },'speed': { 'Activate_Speed': "True", 'Add_Flow_Rate': "True", - 'Bridge_Feed_Rate_Multiplier_ratio': defaultSetting, - 'Bridge_Flow_Rate_Multiplier_ratio': defaultSetting, - 'Duty_Cyle_at_Beginning_portion': defaultSetting, - 'Duty_Cyle_at_Ending_portion': defaultSetting, + 'Bridge_Feed_Rate_Multiplier_ratio': DEFSET, + 'Bridge_Flow_Rate_Multiplier_ratio': DEFSET, + 'Duty_Cyle_at_Beginning_portion': DEFSET, + 'Duty_Cyle_at_Ending_portion': DEFSET, 'Feed_Rate_mm/s': storedSetting("print_speed"), 'Flow_Rate_Setting_float': storedSetting("print_speed"), - 'Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio': defaultSetting, - 'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': defaultSetting, - 'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': defaultSetting, - 'Object_First_Layer_Flow_Rate_Infill_Multiplier_ratio': defaultSetting, - 'Object_First_Layer_Flow_Rate_Perimeter_Multiplier_ratio': defaultSetting, - 'Object_First_Layers_Amount_Of_Layers_For_Speed_Change': defaultSetting, - 'Orbital_Feed_Rate_over_Operating_Feed_Rate_ratio': defaultSetting, - 'Maximum_Z_Feed_Rate_mm/s': defaultSetting, - 'Perimeter_Feed_Rate_Multiplier_ratio': defaultSetting, - 'Perimeter_Flow_Rate_Multiplier_ratio': defaultSetting, + 'Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio, + 'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio, + 'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': firstLayerSpeedRatio, + 'Object_First_Layer_Flow_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio, + 'Object_First_Layer_Flow_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio, + 'Object_First_Layers_Amount_Of_Layers_For_Speed_Change': DEFSET, + 'Orbital_Feed_Rate_over_Operating_Feed_Rate_ratio': DEFSET, + 'Maximum_Z_Feed_Rate_mm/s': DEFSET, + 'Perimeter_Feed_Rate_Multiplier_ratio': DEFSET, + 'Perimeter_Flow_Rate_Multiplier_ratio': DEFSET, 'Travel_Feed_Rate_mm/s': storedSetting("travel_speed"), },'temperature': { - 'Activate_Temperature': defaultSetting,#ifSettingAboveZero('print_temperature'), - 'Cooling_Rate_Celcius/second': defaultSetting, - 'Heating_Rate_Celcius/second': defaultSetting, - 'Base_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), - 'Interface_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), - 'Object_First_Layer_Infill_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), - 'Object_First_Layer_Perimeter_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), - 'Object_Next_Layers_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), - 'Support_Layers_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), - 'Supported_Layers_Temperature_Celcius': defaultSetting,#storedSetting("print_temperature"), + 'Activate_Temperature': DEFSET,#ifSettingAboveZero('print_temperature'), + 'Cooling_Rate_Celcius/second': DEFSET, + 'Heating_Rate_Celcius/second': DEFSET, + 'Base_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), + 'Interface_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), + 'Object_First_Layer_Infill_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), + 'Object_First_Layer_Perimeter_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), + 'Object_Next_Layers_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), + 'Support_Layers_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), + 'Supported_Layers_Temperature_Celcius': DEFSET,#storedSetting("print_temperature"), },'raft': { 'Activate_Raft': "True", - 'Add_Raft,_Elevate_Nozzle,_Orbit': defaultSetting, - 'Base_Feed_Rate_Multiplier_ratio': defaultSetting, - 'Base_Flow_Rate_Multiplier_ratio': defaultSetting, - 'Base_Infill_Density_ratio': defaultSetting, - 'Base_Layer_Thickness_over_Layer_Thickness': defaultSetting, + 'Add_Raft,_Elevate_Nozzle,_Orbit': DEFSET, + 'Base_Feed_Rate_Multiplier_ratio': DEFSET, + 'Base_Flow_Rate_Multiplier_ratio': DEFSET, + 'Base_Infill_Density_ratio': DEFSET, + 'Base_Layer_Thickness_over_Layer_Thickness': DEFSET, 'Base_Layers_integer': '0', - 'Base_Nozzle_Lift_over_Base_Layer_Thickness_ratio': defaultSetting, - 'Initial_Circling': defaultSetting, - 'Infill_Overhang_over_Extrusion_Width_ratio': defaultSetting, - 'Interface_Feed_Rate_Multiplier_ratio': defaultSetting, - 'Interface_Flow_Rate_Multiplier_ratio': defaultSetting, - 'Interface_Infill_Density_ratio': defaultSetting, - 'Interface_Layer_Thickness_over_Layer_Thickness': defaultSetting, + 'Base_Nozzle_Lift_over_Base_Layer_Thickness_ratio': DEFSET, + 'Initial_Circling': DEFSET, + 'Infill_Overhang_over_Extrusion_Width_ratio': DEFSET, + 'Interface_Feed_Rate_Multiplier_ratio': DEFSET, + 'Interface_Flow_Rate_Multiplier_ratio': DEFSET, + 'Interface_Infill_Density_ratio': DEFSET, + 'Interface_Layer_Thickness_over_Layer_Thickness': DEFSET, 'Interface_Layers_integer': '0', - 'Interface_Nozzle_Lift_over_Interface_Layer_Thickness_ratio': defaultSetting, - 'Name_of_Support_End_File': defaultSetting, - 'Name_of_Support_Start_File': defaultSetting, - 'Operating_Nozzle_Lift_over_Layer_Thickness_ratio': defaultSetting, - 'Raft_Additional_Margin_over_Length_%': defaultSetting, - 'Raft_Margin_mm': defaultSetting, + 'Interface_Nozzle_Lift_over_Interface_Layer_Thickness_ratio': DEFSET, + 'Name_of_Support_End_File': DEFSET, + 'Name_of_Support_Start_File': DEFSET, + 'Operating_Nozzle_Lift_over_Layer_Thickness_ratio': DEFSET, + 'Raft_Additional_Margin_over_Length_%': DEFSET, + 'Raft_Margin_mm': DEFSET, 'Support_Cross_Hatch': 'False', - 'Support_Flow_Rate_over_Operating_Flow_Rate_ratio': defaultSetting, - 'Support_Gap_over_Perimeter_Extrusion_Width_ratio': defaultSetting, + 'Support_Flow_Rate_over_Operating_Flow_Rate_ratio': DEFSET, + 'Support_Gap_over_Perimeter_Extrusion_Width_ratio': DEFSET, 'Support_Material_Choice_': storedSetting("support"), - 'Support_Minimum_Angle_degrees': defaultSetting, + 'Support_Minimum_Angle_degrees': DEFSET, },'skirt': { 'Skirt_line_count': storedSetting("skirt_line_count"), 'Convex': "True", @@ -198,122 +203,122 @@ def getSkeinPyPyProfileInformation(): 'Layers_To_index': "1", },'chamber': { 'Activate_Chamber': "False", - 'Bed_Temperature_Celcius': defaultSetting, - 'Bed_Temperature_Begin_Change_Height_mm': defaultSetting, - 'Bed_Temperature_End_Change_Height_mm': defaultSetting, - 'Bed_Temperature_End_Celcius': defaultSetting, - 'Chamber_Temperature_Celcius': defaultSetting, - 'Holding_Force_bar': defaultSetting, + 'Bed_Temperature_Celcius': DEFSET, + 'Bed_Temperature_Begin_Change_Height_mm': DEFSET, + 'Bed_Temperature_End_Change_Height_mm': DEFSET, + 'Bed_Temperature_End_Celcius': DEFSET, + 'Chamber_Temperature_Celcius': DEFSET, + 'Holding_Force_bar': DEFSET, },'tower': { 'Activate_Tower': "False", - 'Extruder_Possible_Collision_Cone_Angle_degrees': defaultSetting, - 'Maximum_Tower_Height_layers': defaultSetting, - 'Tower_Start_Layer_integer': defaultSetting, + 'Extruder_Possible_Collision_Cone_Angle_degrees': DEFSET, + 'Maximum_Tower_Height_layers': DEFSET, + 'Tower_Start_Layer_integer': DEFSET, },'jitter': { 'Activate_Jitter': "False", - 'Jitter_Over_Perimeter_Width_ratio': defaultSetting, + 'Jitter_Over_Perimeter_Width_ratio': DEFSET, },'clip': { 'Activate_Clip': "False", - 'Clip_Over_Perimeter_Width_ratio': defaultSetting, - 'Maximum_Connection_Distance_Over_Perimeter_Width_ratio': defaultSetting, + 'Clip_Over_Perimeter_Width_ratio': DEFSET, + 'Maximum_Connection_Distance_Over_Perimeter_Width_ratio': DEFSET, },'smooth': { 'Activate_Smooth': "False", - 'Layers_From_index': defaultSetting, - 'Maximum_Shortening_over_Width_float': defaultSetting, + 'Layers_From_index': DEFSET, + 'Maximum_Shortening_over_Width_float': DEFSET, },'stretch': { 'Activate_Stretch': "False", - 'Cross_Limit_Distance_Over_Perimeter_Width_ratio': defaultSetting, - 'Loop_Stretch_Over_Perimeter_Width_ratio': defaultSetting, - 'Path_Stretch_Over_Perimeter_Width_ratio': defaultSetting, - 'Perimeter_Inside_Stretch_Over_Perimeter_Width_ratio': defaultSetting, - 'Perimeter_Outside_Stretch_Over_Perimeter_Width_ratio': defaultSetting, - 'Stretch_From_Distance_Over_Perimeter_Width_ratio': defaultSetting, + 'Cross_Limit_Distance_Over_Perimeter_Width_ratio': DEFSET, + 'Loop_Stretch_Over_Perimeter_Width_ratio': DEFSET, + 'Path_Stretch_Over_Perimeter_Width_ratio': DEFSET, + 'Perimeter_Inside_Stretch_Over_Perimeter_Width_ratio': DEFSET, + 'Perimeter_Outside_Stretch_Over_Perimeter_Width_ratio': DEFSET, + 'Stretch_From_Distance_Over_Perimeter_Width_ratio': DEFSET, },'skin': { 'Activate_Skin': "False", - 'Horizontal_Infill_Divisions_integer': defaultSetting, - 'Horizontal_Perimeter_Divisions_integer': defaultSetting, - 'Vertical_Divisions_integer': defaultSetting, - 'Hop_When_Extruding_Infill': defaultSetting, - 'Layers_From_index': defaultSetting, + 'Horizontal_Infill_Divisions_integer': DEFSET, + 'Horizontal_Perimeter_Divisions_integer': DEFSET, + 'Vertical_Divisions_integer': DEFSET, + 'Hop_When_Extruding_Infill': DEFSET, + 'Layers_From_index': DEFSET, },'comb': { 'Activate_Comb': "True", - 'Running_Jump_Space_mm': defaultSetting, + 'Running_Jump_Space_mm': DEFSET, },'cool': { 'Activate_Cool': "True", - 'Bridge_Cool_Celcius': defaultSetting, - 'Cool_Type': defaultSetting, - 'Maximum_Cool_Celcius': defaultSetting, + 'Bridge_Cool_Celcius': DEFSET, + 'Cool_Type': DEFSET, + 'Maximum_Cool_Celcius': DEFSET, 'Minimum_Layer_Time_seconds': storedSetting("cool_min_layer_time"), - 'Minimum_Orbital_Radius_millimeters': defaultSetting, - 'Name_of_Cool_End_File': defaultSetting, - 'Name_of_Cool_Start_File': defaultSetting, - 'Orbital_Outset_millimeters': defaultSetting, - 'Turn_Fan_On_at_Beginning': defaultSetting, - 'Turn_Fan_Off_at_Ending': defaultSetting, + 'Minimum_Orbital_Radius_millimeters': DEFSET, + 'Name_of_Cool_End_File': DEFSET, + 'Name_of_Cool_Start_File': DEFSET, + 'Orbital_Outset_millimeters': DEFSET, + 'Turn_Fan_On_at_Beginning': DEFSET, + 'Turn_Fan_Off_at_Ending': DEFSET, },'hop': { 'Activate_Hop': "False", - 'Hop_Over_Layer_Thickness_ratio': defaultSetting, - 'Minimum_Hop_Angle_degrees': defaultSetting, + 'Hop_Over_Layer_Thickness_ratio': DEFSET, + 'Minimum_Hop_Angle_degrees': DEFSET, },'wipe': { 'Activate_Wipe': "False", - 'Arrival_X_mm': defaultSetting, - 'Arrival_Y_mm': defaultSetting, - 'Arrival_Z_mm': defaultSetting, - 'Departure_X_mm': defaultSetting, - 'Departure_Y_mm': defaultSetting, - 'Departure_Z_mm': defaultSetting, - 'Wipe_X_mm': defaultSetting, - 'Wipe_Y_mm': defaultSetting, - 'Wipe_Z_mm': defaultSetting, - 'Wipe_Period_layers': defaultSetting, + 'Arrival_X_mm': DEFSET, + 'Arrival_Y_mm': DEFSET, + 'Arrival_Z_mm': DEFSET, + 'Departure_X_mm': DEFSET, + 'Departure_Y_mm': DEFSET, + 'Departure_Z_mm': DEFSET, + 'Wipe_X_mm': DEFSET, + 'Wipe_Y_mm': DEFSET, + 'Wipe_Z_mm': DEFSET, + 'Wipe_Period_layers': DEFSET, },'oozebane': { 'Activate_Oozebane': "False", - 'After_Startup_Distance_millimeters': defaultSetting, - 'Early_Shutdown_Distance_millimeters': defaultSetting, - 'Early_Startup_Distance_Constant_millimeters': defaultSetting, - 'Early_Startup_Maximum_Distance_millimeters': defaultSetting, - 'First_Early_Startup_Distance_millimeters': defaultSetting, - 'Minimum_Distance_for_Early_Startup_millimeters': defaultSetting, - 'Minimum_Distance_for_Early_Shutdown_millimeters': defaultSetting, - 'Slowdown_Startup_Steps_positive_integer': defaultSetting, + 'After_Startup_Distance_millimeters': DEFSET, + 'Early_Shutdown_Distance_millimeters': DEFSET, + 'Early_Startup_Distance_Constant_millimeters': DEFSET, + 'Early_Startup_Maximum_Distance_millimeters': DEFSET, + 'First_Early_Startup_Distance_millimeters': DEFSET, + 'Minimum_Distance_for_Early_Startup_millimeters': DEFSET, + 'Minimum_Distance_for_Early_Shutdown_millimeters': DEFSET, + 'Slowdown_Startup_Steps_positive_integer': DEFSET, },'dwindle': { 'Activate_Dwindle': "False", - 'End_Rate_Multiplier_ratio': defaultSetting, - 'Pent_Up_Volume_cubic_millimeters': defaultSetting, - 'Slowdown_Steps_positive_integer': defaultSetting, - 'Slowdown_Volume_cubic_millimeters': defaultSetting, + 'End_Rate_Multiplier_ratio': DEFSET, + 'Pent_Up_Volume_cubic_millimeters': DEFSET, + 'Slowdown_Steps_positive_integer': DEFSET, + 'Slowdown_Volume_cubic_millimeters': DEFSET, },'splodge': { 'Activate_Splodge': "False", - 'Initial_Lift_over_Extra_Thickness_ratio': defaultSetting, - 'Initial_Splodge_Feed_Rate_mm/s': defaultSetting, - 'Operating_Splodge_Feed_Rate_mm/s': defaultSetting, - 'Operating_Splodge_Quantity_Length_millimeters': defaultSetting, - 'Initial_Splodge_Quantity_Length_millimeters': defaultSetting, - 'Operating_Lift_over_Extra_Thickness_ratio': defaultSetting, + 'Initial_Lift_over_Extra_Thickness_ratio': DEFSET, + 'Initial_Splodge_Feed_Rate_mm/s': DEFSET, + 'Operating_Splodge_Feed_Rate_mm/s': DEFSET, + 'Operating_Splodge_Quantity_Length_millimeters': DEFSET, + 'Initial_Splodge_Quantity_Length_millimeters': DEFSET, + 'Operating_Lift_over_Extra_Thickness_ratio': DEFSET, },'home': { 'Activate_Home': "False", - 'Name_of_Home_File': defaultSetting, + 'Name_of_Home_File': DEFSET, },'lash': { 'Activate_Lash': "False", - 'X_Backlash_mm': defaultSetting, - 'Y_Backlash_mm': defaultSetting, + 'X_Backlash_mm': DEFSET, + 'Y_Backlash_mm': DEFSET, },'fillet': { 'Activate_Fillet': "False", - 'Arc_Point': defaultSetting, - 'Arc_Radius': defaultSetting, - 'Arc_Segment': defaultSetting, - 'Bevel': defaultSetting, - 'Corner_Feed_Rate_Multiplier_ratio': defaultSetting, - 'Fillet_Radius_over_Perimeter_Width_ratio': defaultSetting, - 'Reversal_Slowdown_Distance_over_Perimeter_Width_ratio': defaultSetting, - 'Use_Intermediate_Feed_Rate_in_Corners': defaultSetting, + 'Arc_Point': DEFSET, + 'Arc_Radius': DEFSET, + 'Arc_Segment': DEFSET, + 'Bevel': DEFSET, + 'Corner_Feed_Rate_Multiplier_ratio': DEFSET, + 'Fillet_Radius_over_Perimeter_Width_ratio': DEFSET, + 'Reversal_Slowdown_Distance_over_Perimeter_Width_ratio': DEFSET, + 'Use_Intermediate_Feed_Rate_in_Corners': DEFSET, },'limit': { 'Activate_Limit': "False", - 'Maximum_Initial_Feed_Rate_mm/s': defaultSetting, + 'Maximum_Initial_Feed_Rate_mm/s': DEFSET, },'unpause': { 'Activate_Unpause': "False", - 'Delay_milliseconds': defaultSetting, - 'Maximum_Speed_ratio': defaultSetting, + 'Delay_milliseconds': DEFSET, + 'Maximum_Speed_ratio': DEFSET, },'dimension': { 'Activate_Dimension': "True", 'Absolute_Extrusion_Distance': "True", @@ -321,9 +326,9 @@ def getSkeinPyPyProfileInformation(): 'Extruder_Retraction_Speed_mm/s': storedSetting('retraction_speed'), 'Filament_Diameter_mm': storedSetting("filament_diameter"), 'Filament_Packing_Density_ratio': storedSetting("filament_density"), - 'Maximum_E_Value_before_Reset_float': defaultSetting, + 'Maximum_E_Value_before_Reset_float': DEFSET, 'Minimum_Travel_for_Retraction_millimeters': storedSetting("retraction_min_travel"), - 'Retract_Within_Island': defaultSetting, + 'Retract_Within_Island': DEFSET, 'Retraction_Distance_millimeters': storedSetting('retraction_amount'), 'Restart_Extra_Distance_millimeters': storedSetting('retraction_extra'), },'alteration': { @@ -331,23 +336,23 @@ def getSkeinPyPyProfileInformation(): 'Name_of_End_File': "end.gcode", 'Name_of_Start_File': "start.gcode", 'Remove_Redundant_Mcode': "True", - 'Replace_Variable_with_Setting': defaultSetting, + 'Replace_Variable_with_Setting': DEFSET, },'export': { 'Activate_Export': "True", - 'Add_Descriptive_Extension': defaultSetting, - 'Add_Export_Suffix': defaultSetting, - 'Add_Profile_Extension': defaultSetting, - 'Add_Timestamp_Extension': defaultSetting, - 'Also_Send_Output_To': defaultSetting, - 'Analyze_Gcode': defaultSetting, - 'Comment_Choice': defaultSetting, - 'Do_Not_Change_Output': defaultSetting, - 'binary_16_byte': defaultSetting, - 'gcode_step': defaultSetting, - 'gcode_time_segment': defaultSetting, - 'gcode_small': defaultSetting, - 'File_Extension': defaultSetting, - 'Name_of_Replace_File': defaultSetting, + 'Add_Descriptive_Extension': DEFSET, + 'Add_Export_Suffix': DEFSET, + 'Add_Profile_Extension': DEFSET, + 'Add_Timestamp_Extension': DEFSET, + 'Also_Send_Output_To': DEFSET, + 'Analyze_Gcode': DEFSET, + 'Comment_Choice': DEFSET, + 'Do_Not_Change_Output': DEFSET, + 'binary_16_byte': DEFSET, + 'gcode_step': DEFSET, + 'gcode_time_segment': DEFSET, + 'gcode_small': DEFSET, + 'File_Extension': DEFSET, + 'Name_of_Replace_File': DEFSET, 'Save_Penultimate_Gcode': "False", } } diff --git a/SkeinPyPy_NewUI/newui/configWindowBase.py b/SkeinPyPy_NewUI/newui/configWindowBase.py new file mode 100644 index 00000000..81da88f4 --- /dev/null +++ b/SkeinPyPy_NewUI/newui/configWindowBase.py @@ -0,0 +1,194 @@ +from __future__ import absolute_import +import __init__ + +import wx, os, platform, types +import ConfigParser + +from fabmetheus_utilities import settings + +from newui import validators + +def main(): + app = wx.App(False) + mainWindow() + app.MainLoop() + +class configWindowBase(wx.Frame): + "A base class for configuration dialogs. Handles creation of settings, and popups" + def __init__(self, title): + super(configWindowBase, self).__init__(None, title=title) + + self.settingControlList = [] + + #Create the popup window + self.popup = wx.PopupWindow(self, wx.BORDER_SIMPLE) + self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK)) + self.popup.setting = None + self.popup.text = wx.StaticText(self.popup, -1, ''); + self.popup.sizer = wx.BoxSizer() + self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1) + self.popup.SetSizer(self.popup.sizer) + + def CreateConfigTab(self, nb, name): + leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb) + nb.AddPage(configPanel, name) + return leftConfigPanel, rightConfigPanel + + def CreateConfigPanel(self, parent): + configPanel = wx.Panel(parent); + leftConfigPanel = wx.Panel(configPanel) + rightConfigPanel = wx.Panel(configPanel) + sizer = wx.GridBagSizer(2, 2) + leftConfigPanel.SetSizer(sizer) + sizer = wx.GridBagSizer(2, 2) + rightConfigPanel.SetSizer(sizer) + sizer = wx.BoxSizer(wx.HORIZONTAL) + configPanel.SetSizer(sizer) + sizer.Add(leftConfigPanel) + sizer.Add(rightConfigPanel) + leftConfigPanel.main = self + rightConfigPanel.main = self + return leftConfigPanel, rightConfigPanel, configPanel + + def OnPopupDisplay(self, setting): + x, y = setting.ctrl.ClientToScreenXY(0, 0) + sx, sy = setting.ctrl.GetSizeTuple() + if platform.system() == "Windows": + #for some reason, under windows, the popup is relative to the main window... + wx, wy = self.ClientToScreenXY(0, 0) + x -= wx + y -= wy + self.popup.setting = setting + self.UpdatePopup(setting) + self.popup.SetPosition((x, y+sy)) + self.popup.Show(True) + + def OnPopupHide(self, e): + self.popup.Show(False) + + def UpdatePopup(self, setting): + if self.popup.setting == setting: + if setting.validationMsg != '': + self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.helpText) + else: + self.popup.text.SetLabel(setting.helpText) + self.popup.text.Wrap(350) + self.popup.Fit() + + def updateProfileToControls(self): + "Update the configuration wx controls to show the new configuration settings" + for setting in self.settingControlList: + setting.SetValue(settings.getSetting(setting.configName)) + +class TitleRow(): + def __init__(self, panel, name): + "Add a title row to the configuration panel" + sizer = panel.GetSizer() + self.title = wx.StaticText(panel, -1, name) + self.title.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD)) + sizer.Add(self.title, (sizer.GetRows(),sizer.GetCols()), (1,3), flag=wx.EXPAND) + sizer.Add(wx.StaticLine(panel), (sizer.GetRows()+1,sizer.GetCols()), (1,3), flag=wx.EXPAND) + sizer.SetRows(sizer.GetRows() + 2) + +class SettingRow(): + def __init__(self, panel, label, configName, defaultValue = '', helpText = 'Help: TODO'): + "Add a setting to the configuration panel" + sizer = panel.GetSizer() + x = sizer.GetRows() + y = sizer.GetCols() + + self.validators = [] + self.validationMsg = '' + self.helpText = helpText + self.configName = configName + self.panel = panel + + self.label = wx.StaticText(panel, -1, label) + if isinstance(defaultValue, types.StringTypes): + self.ctrl = wx.TextCtrl(panel, -1, settings.getSetting(configName, defaultValue)) + else: + self.ctrl = wx.ComboBox(panel, -1, settings.getSetting(configName, defaultValue[0]), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY) + #self.helpButton = wx.Button(panel, -1, "?", style=wx.BU_EXACTFIT) + #self.helpButton.SetToolTip(wx.ToolTip(help)) + + self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingTextChange) + self.ctrl.Bind(wx.EVT_ENTER_WINDOW, lambda e: panel.main.OnPopupDisplay(self)) + self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, panel.main.OnPopupHide) + + panel.main.settingControlList.append(self) + + sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL) + sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|wx.EXPAND) + #sizer.Add(helpButton, (x,y+2)) + sizer.SetRows(x+1) + + def OnSettingTextChange(self, e): + result = validators.SUCCESS + msgs = [] + for validator in self.validators: + res, err = validator.validate() + if res == validators.ERROR: + result = res + elif res == validators.WARNING and result != validators.ERROR: + result = res + if res != validators.SUCCESS: + print err + msgs.append(err) + if result == validators.ERROR: + self.ctrl.SetBackgroundColour('Red') + elif result == validators.WARNING: + self.ctrl.SetBackgroundColour('Yellow') + else: + self.ctrl.SetBackgroundColour(wx.NullColour) + self.ctrl.Refresh() + settings.putSetting(self.configName, self.GetValue()) + + self.validationMsg = '\n'.join(msgs) + self.panel.main.UpdatePopup(self) + + def GetValue(self): + return self.ctrl.GetValue() + + def SetValue(self, value): + self.ctrl.SetValue(value) + +#Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value. +class settingNotify(): + def __init__(self, setting, func): + self.setting = setting + self.setting.validators.append(self) + self.func = func + + def validate(self): + try: + f = float(self.setting.GetValue()) + self.func(f) + return validators.SUCCESS, '' + except ValueError: + return validators.SUCCESS, '' + +def getPreferencePath(): + return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../preferences.ini")) + +def getPreference(name, default): + if not globals().has_key('globalPreferenceParser'): + globalPreferenceParser = ConfigParser.ConfigParser() + globalPreferenceParser.read(getPreferencePath()) + if not globalPreferenceParser.has_option('preference', name): + if not globalPreferenceParser.has_section('preference'): + globalPreferenceParser.add_section('preference') + globalPreferenceParser.set('preference', name, str(default)) + print name + " not found in profile, so using default" + return default + return globalPreferenceParser.get('preference', name) + +def putPreference(name, value): + #Check if we have a configuration file loaded, else load the default. + if not globals().has_key('globalPreferenceParser'): + globalPreferenceParser = ConfigParser.ConfigParser() + globalPreferenceParser.read(getPreferencePath()) + if not globalPreferenceParser.has_section('preference'): + globalPreferenceParser.add_section('preference') + globalPreferenceParser.set('preference', name, str(value)) + globalPreferenceParser.write(open(getPreferencePath(), 'w')) + diff --git a/SkeinPyPy_NewUI/newui/mainWindow.py b/SkeinPyPy_NewUI/newui/mainWindow.py index ed01fec1..483d2571 100644 --- a/SkeinPyPy_NewUI/newui/mainWindow.py +++ b/SkeinPyPy_NewUI/newui/mainWindow.py @@ -6,6 +6,7 @@ import ConfigParser from fabmetheus_utilities import settings +from newui import configWindowBase from newui import preview3d from newui import sliceProgessPanel from newui import alterationPanel @@ -16,31 +17,32 @@ def main(): mainWindow() app.MainLoop() -class mainWindow(wx.Frame): +class mainWindow(configWindowBase.configWindowBase): "Main user interface window" def __init__(self): - super(mainWindow, self).__init__(None, title='SkeinPyPy') + super(mainWindow, self).__init__(title='SkeinPyPy') wx.EVT_CLOSE(self, self.OnClose) menubar = wx.MenuBar() fileMenu = wx.Menu() - fitem = fileMenu.Append(-1, 'Open Profile...', 'Open Profile...') - self.Bind(wx.EVT_MENU, self.OnLoadProfile, fitem) - fitem = fileMenu.Append(-1, 'Save Profile...', 'Save Profile...') - self.Bind(wx.EVT_MENU, self.OnSaveProfile, fitem) - fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quit application') - self.Bind(wx.EVT_MENU, self.OnQuit, fitem) + i = fileMenu.Append(-1, 'Open Profile...', 'Open Profile...') + self.Bind(wx.EVT_MENU, self.OnLoadProfile, i) + i = fileMenu.Append(-1, 'Save Profile...', 'Save Profile...') + self.Bind(wx.EVT_MENU, self.OnSaveProfile, i) + i = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quit application') + self.Bind(wx.EVT_MENU, self.OnQuit, i) menubar.Append(fileMenu, '&File') - #menubar.Append(wx.Menu(), 'Expert') + + expertMenu = wx.Menu() + i = expertMenu.Append(-1, 'Open expert settings...', 'Open expert settings...') + self.Bind(wx.EVT_MENU, self.OnExpertOpen, i) + menubar.Append(expertMenu, 'Expert') self.SetMenuBar(menubar) - wx.ToolTip.SetDelay(0) - self.lastPath = "" - self.filename = getPreference('lastFile', None) + self.filename = configWindowBase.getPreference('lastFile', None) self.progressPanelList = [] - self.settingControlList = [] #Preview window self.preview3d = preview3d.previewPanel(self) @@ -50,85 +52,85 @@ class mainWindow(wx.Frame): (left, right) = self.CreateConfigTab(nb, 'Print config') - TitleRow(left, "Accuracy") - c = SettingRow(left, "Layer height (mm)", 'layer_height', '0.2', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.') + configWindowBase.TitleRow(left, "Accuracy") + c = configWindowBase.SettingRow(left, "Layer height (mm)", 'layer_height', '0.2', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.') validators.validFloat(c, 0.0) validators.warningAbove(c, 0.31, "Thicker layers then 0.3mm usually give bad results and are not recommended.") - c = SettingRow(left, "Wall thickness (mm)", 'wall_thickness', '0.8', 'Thickness of the walls.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines.') + c = configWindowBase.SettingRow(left, "Wall thickness (mm)", 'wall_thickness', '0.8', 'Thickness of the walls.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines.') validators.validFloat(c, 0.0) validators.wallThicknessValidator(c) - TitleRow(left, "Fill") - c = SettingRow(left, "Bottom/Top thickness (mm)", 'solid_layer_thickness', '0.6', 'This controls the thickness of the bottom and top layers, the amount of solid layers put down is calculated by the layer thickness and this value.\nHaving this value a multiply of the layer thickness makes sense. And keep it near your wall thickness to make an evenly strong part.') + configWindowBase.TitleRow(left, "Fill") + c = configWindowBase.SettingRow(left, "Bottom/Top thickness (mm)", 'solid_layer_thickness', '0.6', 'This controls the thickness of the bottom and top layers, the amount of solid layers put down is calculated by the layer thickness and this value.\nHaving this value a multiply of the layer thickness makes sense. And keep it near your wall thickness to make an evenly strong part.') validators.validFloat(c, 0.0) - c = SettingRow(left, "Fill Density (%)", 'fill_density', '20', 'This controls how densily filled the insides of your print will be. For a solid part use 100%, for an empty part use 0%. A value around 20% is usually enough') + c = configWindowBase.SettingRow(left, "Fill Density (%)", 'fill_density', '20', 'This controls how densily filled the insides of your print will be. For a solid part use 100%, for an empty part use 0%. A value around 20% is usually enough') validators.validFloat(c, 0.0, 100.0) - TitleRow(left, "Skirt") - c = SettingRow(left, "Line count", 'skirt_line_count', '1', 'The skirt is a line drawn around the object at the first layer. This helps to prime your extruder, and to see if the object fits on your platform.\nSetting this to 0 will disable the skirt.') + configWindowBase.TitleRow(left, "Skirt") + c = configWindowBase.SettingRow(left, "Line count", 'skirt_line_count', '1', 'The skirt is a line drawn around the object at the first layer. This helps to prime your extruder, and to see if the object fits on your platform.\nSetting this to 0 will disable the skirt.') validators.validInt(c, 0, 10) - c = SettingRow(left, "Start distance (mm)", 'skirt_gap', '6.0', 'The distance between the skirt and the first layer.\nThis is the minimal distance, multiple skirt lines will be put outwards from this distance.') + c = configWindowBase.SettingRow(left, "Start distance (mm)", 'skirt_gap', '6.0', 'The distance between the skirt and the first layer.\nThis is the minimal distance, multiple skirt lines will be put outwards from this distance.') validators.validFloat(c, 0.0) - TitleRow(right, "Speed") - c = SettingRow(right, "Print speed (mm/s)", 'print_speed', '50') + configWindowBase.TitleRow(right, "Speed") + c = configWindowBase.SettingRow(right, "Print speed (mm/s)", 'print_speed', '50') validators.validFloat(c, 1.0) validators.warningAbove(c, 150.0, "It is highly unlikely that your machine can achieve a printing speed above 150mm/s") #Printing temperature is a problem right now, as our start code depends on a heated head. - #TitleRow(right, "Temperature") - #c = SettingRow(right, "Printing temperature", 'print_temperature', '0', 'Temperature used for printing. Set at 0 to pre-heat yourself') + #configWindowBase.TitleRow(right, "Temperature") + #c = configWindowBase.SettingRow(right, "Printing temperature", 'print_temperature', '0', 'Temperature used for printing. Set at 0 to pre-heat yourself') #validators.validFloat(c, 0.0, 350.0) #validators.warningAbove(c, 260.0, "Temperatures above 260C could damage your machine.") - TitleRow(right, "Support") - c = SettingRow(right, "Support type", 'support', ['None', 'Exterior only', 'Everywhere', 'Empty layers only'], 'Type of support structure build.\nNone does not do any support.\nExterior only only creates support on the outside.\nEverywhere creates support even on the insides of the model.\nOnly on empty layers is for stacked objects.') + configWindowBase.TitleRow(right, "Support") + c = configWindowBase.SettingRow(right, "Support type", 'support', ['None', 'Exterior only', 'Everywhere', 'Empty layers only'], 'Type of support structure build.\nNone does not do any support.\nExterior only only creates support on the outside.\nEverywhere creates support even on the insides of the model.\nOnly on empty layers is for stacked objects.') (left, right) = self.CreateConfigTab(nb, 'Machine && Filament') - TitleRow(left, "Machine size") - c = SettingRow(left, "Machine center X (mm)", 'machine_center_x', '100', 'The center of your machine, your print will be placed at this location') + configWindowBase.TitleRow(left, "Machine size") + c = configWindowBase.SettingRow(left, "Machine center X (mm)", 'machine_center_x', '100', 'The center of your machine, your print will be placed at this location') validators.validInt(c, 10) - settingNotify(c, self.preview3d.updateCenterX) - c = SettingRow(left, "Machine center Y (mm)", 'machine_center_y', '100', 'The center of your machine, your print will be placed at this location') + configWindowBase.settingNotify(c, self.preview3d.updateCenterX) + c = configWindowBase.SettingRow(left, "Machine center Y (mm)", 'machine_center_y', '100', 'The center of your machine, your print will be placed at this location') validators.validInt(c, 10) - settingNotify(c, self.preview3d.updateCenterY) + configWindowBase.settingNotify(c, self.preview3d.updateCenterY) #self.AddSetting(left, "Width (mm)", settings.IntSpin().getFromValue(10, "machine_width", None, 1000, 205)) #self.AddSetting(left, "Depth (mm)", settings.IntSpin().getFromValue(10, "machine_depth", None, 1000, 205)) #self.AddSetting(left, "Height (mm)", settings.IntSpin().getFromValue(10, "machine_height", None, 1000, 200)) - TitleRow(left, "Machine nozzle") - c = SettingRow(left, "Nozzle size (mm)", 'nozzle_size', '0.4') + configWindowBase.TitleRow(left, "Machine nozzle") + c = configWindowBase.SettingRow(left, "Nozzle size (mm)", 'nozzle_size', '0.4') validators.validFloat(c, 0.1, 1.0) - TitleRow(left, "Retraction") - c = SettingRow(left, "Minimal travel (mm)", 'retraction_min_travel', '5.0') + configWindowBase.TitleRow(left, "Retraction") + c = configWindowBase.SettingRow(left, "Minimal travel (mm)", 'retraction_min_travel', '5.0') validators.validFloat(c, 0.0) - c = SettingRow(left, "Speed (mm/s)", 'retraction_speed', '13.5') + c = configWindowBase.SettingRow(left, "Speed (mm/s)", 'retraction_speed', '13.5') validators.validFloat(c, 0.1) - c = SettingRow(left, "Distance (mm)", 'retraction_amount', '0.0') + c = configWindowBase.SettingRow(left, "Distance (mm)", 'retraction_amount', '0.0') validators.validFloat(c, 0.0) - c = SettingRow(left, "Extra length on start (mm)", 'retraction_extra', '0.0') + c = configWindowBase.SettingRow(left, "Extra length on start (mm)", 'retraction_extra', '0.0') validators.validFloat(c, 0.0) - TitleRow(right, "Speed") - c = SettingRow(right, "Travel speed (mm/s)", 'travel_speed', '150') + configWindowBase.TitleRow(right, "Speed") + c = configWindowBase.SettingRow(right, "Travel speed (mm/s)", 'travel_speed', '150') validators.validFloat(c, 1.0) validators.warningAbove(c, 300.0, "It is highly unlikely that your machine can achieve a travel speed above 150mm/s") - c = SettingRow(right, "Max Z speed (mm/s)", 'max_z_speed', '1.0') + c = configWindowBase.SettingRow(right, "Max Z speed (mm/s)", 'max_z_speed', '1.0') validators.validFloat(c, 0.5) - c = SettingRow(right, "Bottom layer speed", 'bottom_layer_speed', '25') + c = configWindowBase.SettingRow(right, "Bottom layer speed", 'bottom_layer_speed', '25') validators.validFloat(c, 0.0) - TitleRow(right, "Cool") + configWindowBase.TitleRow(right, "Cool") #c = SettingRow(right, "Cool type", self.plugins['cool'].preferencesDict['Cool_Type']) - c = SettingRow(right, "Minimal layer time (sec)", 'cool_min_layer_time', '10', 'Minimum time spend in a layer, gives the layer time to cool down before the next layer is put on top. If the layer will be placed down too fast the printer will slow down to make sure it has spend atleast this amount of seconds printing this layer.') + c = configWindowBase.SettingRow(right, "Minimal layer time (sec)", 'cool_min_layer_time', '10', 'Minimum time spend in a layer, gives the layer time to cool down before the next layer is put on top. If the layer will be placed down too fast the printer will slow down to make sure it has spend atleast this amount of seconds printing this layer.') validators.validFloat(c, 0.0) - TitleRow(right, "Filament") - c = SettingRow(right, "Diameter (mm)", 'filament_diameter', '2.98', 'Diameter of your filament, as accurately as possible.\nIf you cannot measure this value you will have to callibrate it, a higher number means less extrusion, a smaller number generates more extrusion.') + configWindowBase.TitleRow(right, "Filament") + c = configWindowBase.SettingRow(right, "Diameter (mm)", 'filament_diameter', '2.98', 'Diameter of your filament, as accurately as possible.\nIf you cannot measure this value you will have to callibrate it, a higher number means less extrusion, a smaller number generates more extrusion.') validators.validFloat(c, 1.0) - c = SettingRow(right, "Packing Density", 'filament_density', '1.00', 'Packing density of your filament. This should be 1.00 for PLA and 0.85 for ABS') + c = configWindowBase.SettingRow(right, "Packing Density", 'filament_density', '1.00', 'Packing density of your filament. This should be 1.00 for PLA and 0.85 for ABS') validators.validFloat(c, 0.5, 1.5) nb.AddPage(alterationPanel.alterationPanel(nb), "Start/End-GCode") @@ -150,14 +152,6 @@ class mainWindow(wx.Frame): sizer.Add(sliceButton, (1,2)) self.sizer = sizer - #Create the popup window - self.popup = wx.PopupWindow(self, wx.BORDER_SIMPLE) - self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK)) - self.popup.text = wx.StaticText(self.popup, -1, ''); - self.popup.sizer = wx.BoxSizer() - self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1) - self.popup.SetSizer(self.popup.sizer) - if self.filename != None: self.preview3d.loadModelFile(self.filename) self.lastPath = os.path.split(self.filename)[0] @@ -168,53 +162,6 @@ class mainWindow(wx.Frame): self.Centre() self.Show(True) - def CreateConfigTab(self, nb, name): - configPanel = wx.Panel(nb); - nb.AddPage(configPanel, name) - leftConfigPanel = wx.Panel(configPanel) - rightConfigPanel = wx.Panel(configPanel) - sizer = wx.GridBagSizer(2, 2) - leftConfigPanel.SetSizer(sizer) - sizer = wx.GridBagSizer(2, 2) - rightConfigPanel.SetSizer(sizer) - sizer = wx.BoxSizer(wx.HORIZONTAL) - configPanel.SetSizer(sizer) - sizer.Add(leftConfigPanel) - sizer.Add(rightConfigPanel) - leftConfigPanel.main = self - rightConfigPanel.main = self - return leftConfigPanel, rightConfigPanel - - def OnPopupDisplay(self, setting): - x, y = setting.ctrl.ClientToScreenXY(0, 0) - sx, sy = setting.ctrl.GetSizeTuple() - if setting.validationMsg != '': - self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.helpText) - else: - self.popup.text.SetLabel(setting.helpText) - self.popup.text.Wrap(350) - if platform.system() == "Windows": - #for some reason, under windows, the popup is relative to the main window... - wx, wy = self.ClientToScreenXY(0, 0) - x -= wx - y -= wy - self.popup.SetPosition((x, y+sy)) - self.popup.Fit() - self.popup.Show(True) - - def OnPopupHide(self, e): - self.popup.Show(False) - - def OnSettingTextChange(self, e): - for validator in self.validators: - res, err = validator.validate() - if res == validators.ERROR: - validator.ctrl.SetBackgroundColour('Red') - elif res == validators.WARNING: - validator.ctrl.SetBackgroundColour('Orange') - else: - validator.ctrl.SetBackgroundColour(wx.NullColor) - def OnLoadProfile(self, e): dlg=wx.FileDialog(self, "Select profile file to load", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard("ini files (*.ini)|*.ini") @@ -260,6 +207,9 @@ class mainWindow(wx.Frame): self.SetSize(newSize) self.progressPanelList.append(spp) + def OnExpertOpen(self, e): + pass + def removeSliceProgress(self, spp): self.progressPanelList.remove(spp) newSize = self.GetSize(); @@ -286,111 +236,3 @@ class mainWindow(wx.Frame): settings.saveGlobalProfile(settings.getDefaultProfilePath()) self.Destroy() -class TitleRow(): - def __init__(self, panel, name): - "Add a title row to the configuration panel" - sizer = panel.GetSizer() - self.title = wx.StaticText(panel, -1, name) - self.title.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD)) - sizer.Add(self.title, (sizer.GetRows(),sizer.GetCols()), (1,3), flag=wx.EXPAND) - sizer.Add(wx.StaticLine(panel), (sizer.GetRows()+1,sizer.GetCols()), (1,3), flag=wx.EXPAND) - sizer.SetRows(sizer.GetRows() + 2) - -class SettingRow(): - def __init__(self, panel, label, configName, defaultValue = '', helpText = 'Help: TODO'): - "Add a setting to the configuration panel" - sizer = panel.GetSizer() - x = sizer.GetRows() - y = sizer.GetCols() - - self.validators = [] - self.validationMsg = '' - self.helpText = helpText - self.configName = configName - - self.label = wx.StaticText(panel, -1, label) - if isinstance(defaultValue, types.StringTypes): - self.ctrl = wx.TextCtrl(panel, -1, settings.getSetting(configName, defaultValue)) - else: - self.ctrl = wx.ComboBox(panel, -1, settings.getSetting(configName, defaultValue[0]), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY) - #self.helpButton = wx.Button(panel, -1, "?", style=wx.BU_EXACTFIT) - #self.helpButton.SetToolTip(wx.ToolTip(help)) - - self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingTextChange) - self.ctrl.Bind(wx.EVT_ENTER_WINDOW, lambda e: panel.main.OnPopupDisplay(self)) - self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, panel.main.OnPopupHide) - - panel.main.settingControlList.append(self) - - sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL) - sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|wx.EXPAND) - #sizer.Add(helpButton, (x,y+2)) - sizer.SetRows(x+1) - - def OnSettingTextChange(self, e): - result = validators.SUCCESS - msgs = [] - for validator in self.validators: - res, err = validator.validate() - if res == validators.ERROR: - result = res - elif res == validators.WARNING and result != validators.ERROR: - result = res - if res != validators.SUCCESS: - print err - msgs.append(err) - if result == validators.ERROR: - self.ctrl.SetBackgroundColour('Red') - elif result == validators.WARNING: - self.ctrl.SetBackgroundColour('Yellow') - else: - self.ctrl.SetBackgroundColour(wx.NullColour) - self.ctrl.Refresh() - settings.putSetting(self.configName, self.GetValue()) - self.validationMsg = '\n'.join(msgs) - - def GetValue(self): - return self.ctrl.GetValue() - - def SetValue(self, value): - self.ctrl.SetValue(value) - -#Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value. -class settingNotify(): - def __init__(self, setting, func): - self.setting = setting - self.setting.validators.append(self) - self.func = func - - def validate(self): - try: - f = float(self.setting.GetValue()) - self.func(f) - return validators.SUCCESS, '' - except ValueError: - return validators.SUCCESS, '' - -def getPreferencePath(): - return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../preferences.ini")) - -def getPreference(name, default): - if not globals().has_key('globalPreferenceParser'): - globalPreferenceParser = ConfigParser.ConfigParser() - globalPreferenceParser.read(getPreferencePath()) - if not globalPreferenceParser.has_option('preference', name): - if not globalPreferenceParser.has_section('preference'): - globalPreferenceParser.add_section('preference') - globalPreferenceParser.set('preference', name, str(default)) - print name + " not found in profile, so using default" - return default - return globalPreferenceParser.get('preference', name) - -def putPreference(name, value): - #Check if we have a configuration file loaded, else load the default. - if not globals().has_key('globalPreferenceParser'): - globalPreferenceParser = ConfigParser.ConfigParser() - globalPreferenceParser.read(getPreferencePath()) - if not globalPreferenceParser.has_section('preference'): - globalPreferenceParser.add_section('preference') - globalPreferenceParser.set('preference', name, str(value)) - globalPreferenceParser.write(open(getPreferencePath(), 'w')) diff --git a/SkeinPyPy_NewUI/newui/validators.py b/SkeinPyPy_NewUI/newui/validators.py index 98860943..30c407a4 100644 --- a/SkeinPyPy_NewUI/newui/validators.py +++ b/SkeinPyPy_NewUI/newui/validators.py @@ -18,12 +18,12 @@ class validFloat(): try: f = float(self.setting.GetValue()) if self.minValue != None and f < self.minValue: - return ERROR, 'Should not be below ' + str(self.minValue) + return ERROR, 'This setting should not be below ' + str(self.minValue) if self.maxValue != None and f > self.maxValue: - return ERROR, 'Should not be above ' + str(self.maxValue) + return ERROR, 'This setting should not be above ' + str(self.maxValue) return SUCCESS, '' except ValueError: - return ERROR, str(self.setting.GetValue()) + ' is not a valid number' + return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid number' class validInt(): def __init__(self, setting, minValue = None, maxValue = None): @@ -36,12 +36,12 @@ class validInt(): try: f = int(self.setting.GetValue()) if self.minValue != None and f < self.minValue: - return ERROR, 'Should not be below ' + str(self.minValue) + return ERROR, 'This setting should not be below ' + str(self.minValue) if self.maxValue != None and f > self.maxValue: - return ERROR, 'Should not be above ' + str(self.maxValue) + return ERROR, 'This setting should not be above ' + str(self.maxValue) return SUCCESS, '' except ValueError: - return ERROR, str(self.setting.GetValue()) + ' is not a valid whole number' + return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid whole number' class warningAbove(): def __init__(self, setting, minValueForWarning, warningMessage): From bca89f9ce5f026762ece58c398e390647007a6be Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 27 Feb 2012 16:40:33 +0100 Subject: [PATCH 3/6] Fixed bug when wall width was less then the nozzle size. Added advanced settings (mostly for 'joris' cups) --- .../fabmetheus_utilities/settings.py | 24 +++++++++---- SkeinPyPy_NewUI/newui/advancedConfig.py | 34 +++++++++++++++++++ SkeinPyPy_NewUI/newui/configWindowBase.py | 1 - SkeinPyPy_NewUI/newui/mainWindow.py | 9 +++-- .../skeinforge_plugins/craft_plugins/fill.py | 12 +++++-- 5 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 SkeinPyPy_NewUI/newui/advancedConfig.py diff --git a/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py b/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py index 38de6477..bd4c89b4 100644 --- a/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py +++ b/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py @@ -22,6 +22,9 @@ def storedSetting(name): def ifSettingAboveZero(name): return lambda setting: float(getSetting(name, '0.0')) > 0 +def ifSettingIs(name, value): + return lambda setting: getSetting(name) == value + def storedPercentSetting(name): return lambda setting: float(getSetting(name, setting.value)) / 100 @@ -40,11 +43,16 @@ def calculateEdgeWidth(setting): return lineWidth def calculateShells(setting): - wallThickness = float(getSetting('wall_thickness')) + return calculateShellsImp(float(getSetting('wall_thickness'))) + +def calculateShellsBase(setting): + return calculateShellsImp(float(getSetting('wall_thickness')) + float(getSetting('extra_base_wall_thickness'))) + +def calculateShellsImp(wallThickness): nozzleSize = float(getSetting('nozzle_size')) if wallThickness < nozzleSize: - return wallThickness + return 0 lineCount = int(wallThickness / nozzleSize + 0.0001) lineWidth = wallThickness / lineCount @@ -106,10 +114,12 @@ def getSkeinPyPyProfileInformation(): 'Volume_Fraction_ratio': DEFSET, },'fill': { 'Activate_Fill': "True", + 'Solid_Surface_Top': storedSetting("solid_top"), + 'Override_First_Layer_Sequence': storedSetting("force_first_layer_sequence"), 'Diaphragm_Period_layers': DEFSET, 'Diaphragm_Thickness_layers': DEFSET, 'Extra_Shells_on_Alternating_Solid_Layer_layers': calculateShells, - 'Extra_Shells_on_Base_layers': calculateShells, + 'Extra_Shells_on_Base_layers': calculateShellsBase, 'Extra_Shells_on_Sparse_Layer_layers': calculateShells, 'Grid_Circle_Separation_over_Perimeter_Width_ratio': DEFSET, 'Grid_Extra_Overlap_ratio': DEFSET, @@ -119,10 +129,10 @@ def getSkeinPyPyProfileInformation(): 'Infill_Begin_Rotation_degrees': DEFSET, 'Infill_Begin_Rotation_Repeat_layers': DEFSET, 'Infill_Odd_Layer_Extra_Rotation_degrees': DEFSET, - 'Grid_Circular': DEFSET, - 'Grid_Hexagonal': DEFSET, - 'Grid_Rectangular': DEFSET, - 'Line': DEFSET, + 'Grid_Circular': ifSettingIs('infill_type', 'Grid Circular'), + 'Grid_Hexagonal': ifSettingIs('infill_type', 'Grid Hexagonal'), + 'Grid_Rectangular': ifSettingIs('infill_type', 'Grid Rectangular'), + 'Line': ifSettingIs('infill_type', 'Line'), 'Infill_Perimeter_Overlap_ratio': DEFSET, 'Infill_Solidity_ratio': storedPercentSetting('fill_density'), 'Infill_Width': storedSetting("nozzle_size"), diff --git a/SkeinPyPy_NewUI/newui/advancedConfig.py b/SkeinPyPy_NewUI/newui/advancedConfig.py new file mode 100644 index 00000000..6bdfe8d3 --- /dev/null +++ b/SkeinPyPy_NewUI/newui/advancedConfig.py @@ -0,0 +1,34 @@ +from __future__ import absolute_import +import __init__ + +import wx, os, platform, types +import ConfigParser + +from fabmetheus_utilities import settings + +from newui import configWindowBase +from newui import preview3d +from newui import sliceProgessPanel +from newui import alterationPanel +from newui import validators + +class advancedConfigWindow(configWindowBase.configWindowBase): + "Advanced configuration window" + def __init__(self): + super(advancedConfigWindow, self).__init__(title='Advanced config') + + left, right, main = self.CreateConfigPanel(self) + + configWindowBase.TitleRow(left, "Accuracy") + c = configWindowBase.SettingRow(left, "Extra Wall thickness for bottom/top (mm)", 'extra_base_wall_thickness', '0.0', 'Additional perimeter thickness of the bottom layer.') + validators.validFloat(c, 0.0) + validators.wallThicknessValidator(c) + + configWindowBase.TitleRow(left, "Infill") + c = configWindowBase.SettingRow(left, "Infill pattern", 'infill_type', ['Line', 'Grid Circular', 'Grid Hexagonal', 'Grid Rectangular'], 'Pattern of the none-solid infill. Line is default, but grids can provide a strong print.') + c = configWindowBase.SettingRow(left, "Solid infill top", 'solid_top', ['True', 'False'], 'Create a solid top surface, if set to false the top is filled with the fill percentage. Useful for cups.') + c = configWindowBase.SettingRow(left, "Force first layer sequence", 'force_first_layer_sequence', ['True', 'False'], 'This setting forces the order of the first layer to be \'Perimeter > Loops > Infill\'') + + main.Fit() + self.Fit() + diff --git a/SkeinPyPy_NewUI/newui/configWindowBase.py b/SkeinPyPy_NewUI/newui/configWindowBase.py index 81da88f4..730cb733 100644 --- a/SkeinPyPy_NewUI/newui/configWindowBase.py +++ b/SkeinPyPy_NewUI/newui/configWindowBase.py @@ -132,7 +132,6 @@ class SettingRow(): elif res == validators.WARNING and result != validators.ERROR: result = res if res != validators.SUCCESS: - print err msgs.append(err) if result == validators.ERROR: self.ctrl.SetBackgroundColour('Red') diff --git a/SkeinPyPy_NewUI/newui/mainWindow.py b/SkeinPyPy_NewUI/newui/mainWindow.py index 483d2571..4e6231e7 100644 --- a/SkeinPyPy_NewUI/newui/mainWindow.py +++ b/SkeinPyPy_NewUI/newui/mainWindow.py @@ -7,6 +7,7 @@ import ConfigParser from fabmetheus_utilities import settings from newui import configWindowBase +from newui import advancedConfig from newui import preview3d from newui import sliceProgessPanel from newui import alterationPanel @@ -155,7 +156,7 @@ class mainWindow(configWindowBase.configWindowBase): if self.filename != None: self.preview3d.loadModelFile(self.filename) self.lastPath = os.path.split(self.filename)[0] - + self.updateProfileToControls() self.Fit() @@ -186,7 +187,7 @@ class mainWindow(configWindowBase.configWindowBase): dlg.SetWildcard("OBJ, STL files (*.stl;*.obj)|*.stl;*.obj") if dlg.ShowModal() == wx.ID_OK: self.filename=dlg.GetPath() - putPreference('lastFile', self.filename) + configWindowBase.putPreference('lastFile', self.filename) if not(os.path.exists(self.filename)): return self.lastPath = os.path.split(self.filename)[0] @@ -208,7 +209,9 @@ class mainWindow(configWindowBase.configWindowBase): self.progressPanelList.append(spp) def OnExpertOpen(self, e): - pass + acw = advancedConfig.advancedConfigWindow() + acw.Centre() + acw.Show(True) def removeSliceProgress(self, spp): self.progressPanelList.remove(spp) diff --git a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py index 75ea0f20..7cf5bcce 100644 --- a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py +++ b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py @@ -769,6 +769,8 @@ class FillRepository: self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Fill', self, '') self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Fill') self.activateFill = settings.BooleanSetting().getFromValue('Activate Fill', self, True) + self.solidSurfaceTop = settings.BooleanSetting().getFromValue('Solid Surface Top', self, True) + self.overrideFirstLayerSequence = settings.BooleanSetting().getFromValue('Override First Layer Sequence', self, True) settings.LabelSeparator().getFromRepository(self) settings.LabelDisplay().getFromName('- Diaphragm -', self ) self.diaphragmPeriod = settings.IntSpin().getFromValue( 20, 'Diaphragm Period (layers):', self, 200, 100 ) @@ -862,8 +864,12 @@ class FillSkein: self.distanceFeedRate.addLine('( %s )' % rotatedLayer.z) if layerRemainder >= int(round(self.repository.diaphragmThickness.value)): for surroundingIndex in xrange(1, self.solidSurfaceThickness + 1): - self.addRotatedCarve(layerIndex, -surroundingIndex, reverseRotation, surroundingCarves) - self.addRotatedCarve(layerIndex, surroundingIndex, reverseRotation, surroundingCarves) + if self.repository.solidSurfaceTop.value: + self.addRotatedCarve(layerIndex, -surroundingIndex, reverseRotation, surroundingCarves) + self.addRotatedCarve(layerIndex, surroundingIndex, reverseRotation, surroundingCarves) + else: + self.addRotatedCarve(layerIndex, -surroundingIndex, reverseRotation, surroundingCarves) + self.addRotatedCarve(layerIndex, -surroundingIndex, reverseRotation, surroundingCarves) if len(surroundingCarves) < self.doubleSolidSurfaceThickness: extraShells = self.repository.extraShellsAlternatingSolidLayer.value if self.lastExtraShells != self.repository.extraShellsBase.value: @@ -1085,7 +1091,7 @@ class FillSkein: self.oldOrderedLocation = getLowerLeftCorner(nestedRings) extrusionHalfWidth = 0.5 * self.infillWidth threadSequence = self.threadSequence - if layerIndex < 1: + if layerIndex < 1 and self.repository.overrideFirstLayerSequence.value: threadSequence = ['edge', 'loops', 'infill'] euclidean.addToThreadsRemove(extrusionHalfWidth, nestedRings, self.oldOrderedLocation, self, threadSequence) if testLoops != None: From e7a860124601cdfa5f320a93c20eb62c9e339cb8 Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 27 Feb 2012 17:14:51 +0100 Subject: [PATCH 4/6] Added joris plugin Added bunch of advanced settings for cups/vases Added missing help tooltips --- .../skeinforge_plugins/craft_plugins/joris.py | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py diff --git a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py new file mode 100644 index 00000000..944707b7 --- /dev/null +++ b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py @@ -0,0 +1,188 @@ +""" +This page is in the table of contents. +The Joris plugin makes the perimiter slowly increase in Z over the layer. This will make vases/cups without a z blob. + +==Operation== +The default 'Activate Joris' checkbox is off. When it is on, the Joris plugin will do it's work. + +==Settings== +===Layers From=== +Default: 1 + +Defines which layer of the print the joris process starts from. + +==Tips== + +==Examples== + +""" + +from __future__ import absolute_import +#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. +import __init__ + +from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret +from fabmetheus_utilities.geometry.solids import triangle_mesh +from fabmetheus_utilities.vector3 import Vector3 +from fabmetheus_utilities import archive +from fabmetheus_utilities import euclidean +from fabmetheus_utilities import gcodec +from fabmetheus_utilities import intercircle +from fabmetheus_utilities import settings +from skeinforge_application.skeinforge_utilities import skeinforge_craft +from skeinforge_application.skeinforge_utilities import skeinforge_polyfile +from skeinforge_application.skeinforge_utilities import skeinforge_profile +import sys + + +__author__ = 'Daid (daid303@gmail.com' +__date__ = '$Date: 2012/24/01 $' +__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' + + +def getCraftedText(fileName, gcodeText, repository=None): + 'Joris a gcode linear move text.' + return getCraftedTextFromText(archive.getTextIfEmpty(fileName, gcodeText), repository) + +def getCraftedTextFromText(gcodeText, repository=None): + 'Joris a gcode linear move text.' + if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'Joris'): + return gcodeText + if repository == None: + repository = settings.getReadRepository(JorisRepository()) + if not repository.activateJoris.value: + return gcodeText + return JorisSkein().getCraftedGcode(gcodeText, repository) + +def getIsMinimumSides(loops, sides=3): + 'Determine if all the loops have at least the given number of sides.' + for loop in loops: + if len(loop) < sides: + return False + return True + +def getNewRepository(): + 'Get new repository.' + return JorisRepository() + +def writeOutput(fileName, shouldAnalyze=True): + 'Joris a gcode linear move file. Chain Joris the gcode if it is not already Jorised.' + skeinforge_craft.writeChainTextWithNounMessage(fileName, 'joris', shouldAnalyze) + + +class JorisRepository: + 'A class to handle the Joris settings.' + def __init__(self): + 'Set the default settings, execute title & settings fileName.' + skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.joris.html', self ) + self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Joris', self, '') + self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Joris') + self.activateJoris = settings.BooleanSetting().getFromValue('Activate Joris', self, False) + settings.LabelSeparator().getFromRepository(self) + self.layersFrom = settings.IntSpin().getSingleIncrementFromValue(0, 'Layers From (index):', self, 912345678, 1) + self.executeTitle = 'Joris' + + def execute(self): + 'Joris button has been clicked.' + fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) + for fileName in fileNames: + writeOutput(fileName) + + +class JorisSkein: + 'A class to Joris a skein of extrusions.' + def __init__(self): + 'Initialize.' + self.distanceFeedRate = gcodec.DistanceFeedRate() + self.lines = None + self.layerIndex = -1 + self.feedRateMinute = 959.0 + self.travelFeedRateMinute = 957.0 + self.perimeter = None + self.oldLocation = None + + def getCraftedGcode( self, gcodeText, repository ): + 'Parse gcode text and store the skin gcode.' + self.lines = archive.getTextLines(gcodeText) + self.repository = repository + self.layersFromBottom = repository.layersFrom.value + self.parseInitialization() + for self.lineIndex in xrange(self.lineIndex, len(self.lines)): + line = self.lines[self.lineIndex] + self.parseLine(line) + return gcodec.getGcodeWithoutDuplication('M108', self.distanceFeedRate.output.getvalue()) + + def parseInitialization(self): + 'Parse gcode initialization and store the parameters.' + for self.lineIndex in xrange(len(self.lines)): + line = self.lines[self.lineIndex] + splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) + firstWord = gcodec.getFirstWord(splitLine) + self.distanceFeedRate.parseSplitLine(firstWord, splitLine) + if firstWord == '(': + self.layerThickness = float(splitLine[1]) + elif firstWord == '()': + self.distanceFeedRate.addTagBracketedProcedure('skin') + return + elif firstWord == '(': + self.travelFeedRateMinute = 60.0 * float(splitLine[1]) + self.distanceFeedRate.addLine(line) + + def parseLine(self, line): + 'Parse a gcode line and add it to the skin skein.' + splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) + if len(splitLine) < 1: + return + firstWord = splitLine[0] + if firstWord == 'G1': + self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) + location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) + self.oldLocation = location + if self.perimeter != None: + self.perimeter.append(location.dropAxis()) + return + elif firstWord == '(': + self.layerIndex += 1 + settings.printProgress(self.layerIndex, 'joris') + elif firstWord == 'M108': + self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) + elif firstWord == '(': + if self.layerIndex >= self.layersFromBottom: + self.perimeter = [] + elif firstWord == '()': + self.addJorisedPerimeter() + self.distanceFeedRate.addLine(line) + + def addJorisedPerimeter(self): + 'Add skinned perimeter.' + if self.perimeter == None: + return + #Calculate the total length of the perimeter. + p = self.oldLocation.dropAxis() + perimeterLength = 0; + for point in self.perimeter[1 :]: + perimeterLength += abs( point - p ); + p = point + + #Build the perimeter with an increasing Z over the length. + p = self.oldLocation.dropAxis() + len = 0; + self.distanceFeedRate.addLine('M101') # Turn extruder on. + for point in self.perimeter[1 :]: + len += abs( point - p ); + p = point + self.distanceFeedRate.addGcodeMovementZWithFeedRate(self.feedRateMinute, point, self.oldLocation.z + self.layerThickness * len / perimeterLength) + self.distanceFeedRate.addLine('M103') # Turn extruder off. + self.perimeter = None + + + +def main(): + 'Display the skin dialog.' + if len(sys.argv) > 1: + writeOutput(' '.join(sys.argv[1 :])) + else: + settings.startMainLoopFromConstructor(getNewRepository()) + +if __name__ == '__main__': + main() From 36c1bc7c0ff7f721b72aefb4788f1fabe6d1f69e Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 27 Feb 2012 17:21:50 +0100 Subject: [PATCH 5/6] . --- .../fabmetheus_utilities/settings.py | 5 ++++- SkeinPyPy_NewUI/newui/advancedConfig.py | 11 ++++++++--- SkeinPyPy_NewUI/newui/mainWindow.py | 18 +++++++++--------- SkeinPyPy_NewUI/newui/sliceProgessPanel.py | 1 + .../skeinforge_plugins/craft_plugins/joris.py | 9 +++++---- .../profile_plugins/extrusion.py | 2 +- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py b/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py index bd4c89b4..2c46aa8b 100644 --- a/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py +++ b/SkeinPyPy_NewUI/fabmetheus_utilities/settings.py @@ -139,7 +139,7 @@ def getSkeinPyPyProfileInformation(): 'Solid_Surface_Thickness_layers': calculateSolidLayerCount, 'Start_From_Choice': DEFSET, 'Surrounding_Angle_degrees': DEFSET, - 'Thread_Sequence_Choice': DEFSET, + 'Thread_Sequence_Choice': storedSetting('sequence'), },'multiply': { 'Activate_Multiply': "True", 'Center_X_mm': storedSetting("machine_center_x"), @@ -211,6 +211,9 @@ def getSkeinPyPyProfileInformation(): 'Convex': "True", 'Gap_Width_mm': storedSetting("skirt_gap"), 'Layers_To_index': "1", + },'joris': { + 'Activate_Joris': storedSetting("joris"), + 'Layers_From_index': calculateSolidLayerCount, },'chamber': { 'Activate_Chamber': "False", 'Bed_Temperature_Celcius': DEFSET, diff --git a/SkeinPyPy_NewUI/newui/advancedConfig.py b/SkeinPyPy_NewUI/newui/advancedConfig.py index 6bdfe8d3..641e039d 100644 --- a/SkeinPyPy_NewUI/newui/advancedConfig.py +++ b/SkeinPyPy_NewUI/newui/advancedConfig.py @@ -20,14 +20,19 @@ class advancedConfigWindow(configWindowBase.configWindowBase): left, right, main = self.CreateConfigPanel(self) configWindowBase.TitleRow(left, "Accuracy") - c = configWindowBase.SettingRow(left, "Extra Wall thickness for bottom/top (mm)", 'extra_base_wall_thickness', '0.0', 'Additional perimeter thickness of the bottom layer.') + c = configWindowBase.SettingRow(left, "Extra Wall thickness for bottom/top (mm)", 'extra_base_wall_thickness', '0.0', 'Additional wall thickness of the bottom and top layers.') validators.validFloat(c, 0.0) validators.wallThicknessValidator(c) + configWindowBase.TitleRow(left, "Sequence") + c = configWindowBase.SettingRow(left, "Print order sequence", 'sequence', ['Loops > Perimeter > Infill', 'Loops > Infill > Perimeter', 'Infill > Loops > Perimeter', 'Infill > Perimeter > Loops', 'Perimeter > Infill > Loops', 'Perimeter > Loops > Infill'], 'Sequence of printing. The perimeter is the outer print edge, the loops are the insides of the walls, and the infill is the insides.'); + c = configWindowBase.SettingRow(left, "Force first layer sequence", 'force_first_layer_sequence', ['True', 'False'], 'This setting forces the order of the first layer to be \'Perimeter > Loops > Infill\'') configWindowBase.TitleRow(left, "Infill") c = configWindowBase.SettingRow(left, "Infill pattern", 'infill_type', ['Line', 'Grid Circular', 'Grid Hexagonal', 'Grid Rectangular'], 'Pattern of the none-solid infill. Line is default, but grids can provide a strong print.') - c = configWindowBase.SettingRow(left, "Solid infill top", 'solid_top', ['True', 'False'], 'Create a solid top surface, if set to false the top is filled with the fill percentage. Useful for cups.') - c = configWindowBase.SettingRow(left, "Force first layer sequence", 'force_first_layer_sequence', ['True', 'False'], 'This setting forces the order of the first layer to be \'Perimeter > Loops > Infill\'') + c = configWindowBase.SettingRow(left, "Solid infill top", 'solid_top', ['True', 'False'], 'Create a solid top surface, if set to false the top is filled with the fill percentage. Useful for cups/vases.') + + configWindowBase.TitleRow(left, "Joris") + c = configWindowBase.SettingRow(left, "Joris the outer edge", 'joris', ['False', 'True'], '[Joris] is a code name for smoothing out the Z move of the outer edge. This will create a steady Z increase over the whole print. It is intended to be used with a single walled wall thickness to make cups/vases.') main.Fit() self.Fit() diff --git a/SkeinPyPy_NewUI/newui/mainWindow.py b/SkeinPyPy_NewUI/newui/mainWindow.py index 4e6231e7..b2e06fe0 100644 --- a/SkeinPyPy_NewUI/newui/mainWindow.py +++ b/SkeinPyPy_NewUI/newui/mainWindow.py @@ -74,7 +74,7 @@ class mainWindow(configWindowBase.configWindowBase): validators.validFloat(c, 0.0) configWindowBase.TitleRow(right, "Speed") - c = configWindowBase.SettingRow(right, "Print speed (mm/s)", 'print_speed', '50') + c = configWindowBase.SettingRow(right, "Print speed (mm/s)", 'print_speed', '50', 'Speed at which printing happens. A well adjusted Ultimaker can reach 150mm/s, but for good quality prints you want to print slower. Printing speed depends on a lot of factors. So you will be experimenting with optimal settings for this.') validators.validFloat(c, 1.0) validators.warningAbove(c, 150.0, "It is highly unlikely that your machine can achieve a printing speed above 150mm/s") @@ -101,26 +101,26 @@ class mainWindow(configWindowBase.configWindowBase): #self.AddSetting(left, "Height (mm)", settings.IntSpin().getFromValue(10, "machine_height", None, 1000, 200)) configWindowBase.TitleRow(left, "Machine nozzle") - c = configWindowBase.SettingRow(left, "Nozzle size (mm)", 'nozzle_size', '0.4') + c = configWindowBase.SettingRow(left, "Nozzle size (mm)", 'nozzle_size', '0.4', 'The nozzle size is very important, this is used to calculate the line width of the infill, and used to calculate the amount of outside wall lines and thickness for the wall thickness you entered in the print settings.') validators.validFloat(c, 0.1, 1.0) configWindowBase.TitleRow(left, "Retraction") - c = configWindowBase.SettingRow(left, "Minimal travel (mm)", 'retraction_min_travel', '5.0') + c = configWindowBase.SettingRow(left, "Minimal travel (mm)", 'retraction_min_travel', '5.0', 'Minimal amount of travel needed for a retraction to happen at all. To make sure you do not get a lot of retractions in a small area') validators.validFloat(c, 0.0) - c = configWindowBase.SettingRow(left, "Speed (mm/s)", 'retraction_speed', '13.5') + c = configWindowBase.SettingRow(left, "Speed (mm/s)", 'retraction_speed', '13.5', 'Speed at which the filament is retracted') validators.validFloat(c, 0.1) - c = configWindowBase.SettingRow(left, "Distance (mm)", 'retraction_amount', '0.0') + c = configWindowBase.SettingRow(left, "Distance (mm)", 'retraction_amount', '0.0', 'Amount of retraction, set at 0 for no retraction at all.') validators.validFloat(c, 0.0) - c = configWindowBase.SettingRow(left, "Extra length on start (mm)", 'retraction_extra', '0.0') + c = configWindowBase.SettingRow(left, "Extra length on start (mm)", 'retraction_extra', '0.0', 'Extra extrusion amount when restarting after a retraction, to better "Prime" your extruder') validators.validFloat(c, 0.0) configWindowBase.TitleRow(right, "Speed") - c = configWindowBase.SettingRow(right, "Travel speed (mm/s)", 'travel_speed', '150') + c = configWindowBase.SettingRow(right, "Travel speed (mm/s)", 'travel_speed', '150', 'Speed at which travel moves are done') validators.validFloat(c, 1.0) validators.warningAbove(c, 300.0, "It is highly unlikely that your machine can achieve a travel speed above 150mm/s") - c = configWindowBase.SettingRow(right, "Max Z speed (mm/s)", 'max_z_speed', '1.0') + c = configWindowBase.SettingRow(right, "Max Z speed (mm/s)", 'max_z_speed', '1.0', 'Speed at which Z moves are done.') validators.validFloat(c, 0.5) - c = configWindowBase.SettingRow(right, "Bottom layer speed", 'bottom_layer_speed', '25') + c = configWindowBase.SettingRow(right, "Bottom layer speed (mm/s)", 'bottom_layer_speed', '25', 'Print speed for the bottom layer, you want to print the first layer slower so it sticks better to the printer bed.') validators.validFloat(c, 0.0) configWindowBase.TitleRow(right, "Cool") diff --git a/SkeinPyPy_NewUI/newui/sliceProgessPanel.py b/SkeinPyPy_NewUI/newui/sliceProgessPanel.py index 2c181ac0..a3d3c705 100644 --- a/SkeinPyPy_NewUI/newui/sliceProgessPanel.py +++ b/SkeinPyPy_NewUI/newui/sliceProgessPanel.py @@ -28,6 +28,7 @@ class sliceProgessPanel(wx.Panel): 'speed': 12.759510994, 'raft': 31.4580039978, 'skirt': 19.3436040878, + 'joris': 1.0, 'comb': 23.7805759907, 'cool': 27.148763895, 'dimension': 90.4914340973 diff --git a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py index 944707b7..2c7fdbe9 100644 --- a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py +++ b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/craft_plugins/joris.py @@ -129,11 +129,12 @@ class JorisSkein: self.distanceFeedRate.addLine(line) def parseLine(self, line): - 'Parse a gcode line and add it to the skin skein.' + 'Parse a gcode line and add it to the joris skein.' splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) if len(splitLine) < 1: return firstWord = splitLine[0] + print 'joris:' + firstWord if firstWord == 'G1': self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) @@ -146,15 +147,15 @@ class JorisSkein: settings.printProgress(self.layerIndex, 'joris') elif firstWord == 'M108': self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - elif firstWord == '(': + elif firstWord == '(': if self.layerIndex >= self.layersFromBottom: self.perimeter = [] - elif firstWord == '()': + elif firstWord == '()': self.addJorisedPerimeter() self.distanceFeedRate.addLine(line) def addJorisedPerimeter(self): - 'Add skinned perimeter.' + 'Add jorised perimeter.' if self.perimeter == None: return #Calculate the total length of the perimeter. diff --git a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py index e32917b5..e8f9a9a9 100644 --- a/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py +++ b/SkeinPyPy_NewUI/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py @@ -28,7 +28,7 @@ __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agp def getCraftSequence(): 'Get the extrusion craft sequence.' - return 'carve scale bottom preface widen inset fill multiply speed temperature raft skirt chamber tower jitter clip smooth stretch skin comb cool hop wipe oozebane dwindle splodge home lash fillet limit unpause dimension alteration export'.split() + return 'carve scale bottom preface widen inset fill multiply speed temperature raft skirt chamber tower jitter clip smooth stretch skin joris comb cool hop wipe oozebane dwindle splodge home lash fillet limit unpause dimension alteration export'.split() def getNewRepository(): 'Get new repository.' From 4ee638898ef1bfbcc657ecdced336fe72e4c740c Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 27 Feb 2012 17:29:14 +0100 Subject: [PATCH 6/6] Updated start/end code with correct style comments (not evil comments) --- .../alterations/end.gcode | 17 ++++---- .../alterations/start.gcode | 43 ++++++++----------- build.sh | 2 +- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/SkeinPyPy_NewUI/skeinforge_application/alterations/end.gcode b/SkeinPyPy_NewUI/skeinforge_application/alterations/end.gcode index 64fe937c..912ed447 100644 --- a/SkeinPyPy_NewUI/skeinforge_application/alterations/end.gcode +++ b/SkeinPyPy_NewUI/skeinforge_application/alterations/end.gcode @@ -1,9 +1,8 @@ -(start of end.gcode) -M104 S0 (extruder heat off) -M106 (fan on) -G91 (relative positioning) -G1 Z+10 E-5 F400 (move Z up a bit and retract filament by 5mm) -G28 X0 Y0 (move X/Y to min endstops, so the head is out of the way) -M84 (steppers off) -G90 (absolute positioning) -(end of end.gcode) +M104 S0 ;extruder heat off +M106 ;fan on +G91 ;relative positioning +G1 Z+10 E-5 F400 ;move Z up a bit and retract filament by 5mm +G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way +M84 ;steppers off +G90 ;absolute positioning + diff --git a/SkeinPyPy_NewUI/skeinforge_application/alterations/start.gcode b/SkeinPyPy_NewUI/skeinforge_application/alterations/start.gcode index 4c309550..1ccaadc2 100644 --- a/SkeinPyPy_NewUI/skeinforge_application/alterations/start.gcode +++ b/SkeinPyPy_NewUI/skeinforge_application/alterations/start.gcode @@ -1,29 +1,24 @@ -(start of start.txt) -G21 (metric values) +G21 ;metric values +G90 ;absolute positioning G21 -G21 (all the extra G21 commands are comments - skeinforge eats lines without a gcode) +G28 X0 Y0 ;move X/Y to min endstops +G28 Z0 ;move Z to min endstops + +; if your prints start too high, try changing the Z0.0 below +; to Z1.0 - the number after the Z is the actual, physical +; height of the nozzle in mm. This can take some messing around +; with to get just right... +G92 X0 Y0 Z0 E0 ;reset software position to front/left/z=0.0 G21 -G90 (absolute positioning) +G1 Z15.0 F400 ;move the platform down 15mm +G92 E0 ;zero the extruded length G21 -G28 X0 Y0 (move X/Y to min endstops) -G28 Z0 (move Z to min endstops) +G1 F75 E5 ;extrude 5mm of feed stock +G1 F75 E3.5 ;reverse feed stock by 1.5mm +G92 E0 ;zero the extruded length again G21 -G21 ( if your prints start too high, try changing the Z0.0 below ) -G21 ( to Z1.0 - the number after the Z is the actual, physical ) -G21 ( height of the nozzle in mm. This can take some messing around ) -G21 ( with to get just right... ) +M1 ;Clean the nozzle then press YES to continue... G21 -G92 X0 Y0 Z0 E0 (reset software position to front/left/z=0.0) -G21 -G1 Z15.0 F400 (move the platform down 15mm) -G92 E0 (zero the extruded length) -G21 -G1 F75 E5 (extrude 5mm of feed stock) -G1 F75 E3.5 (reverse feed stock by 1.5mm) -G92 E0 (zero the extruded length again) -G21 -M1 (Clean the nozzle then press YES to continue...) -G21 -G1 X100 Y100 F3500 (go to the middle of the platform) -G1 Z0.0 F400 (back to Z=0 and start the print!) -(end of start.txt) +G1 X100 Y100 F3500 ;go to the middle of the platform +G1 Z0.0 F400 ;back to Z=0 and start the print! + diff --git a/build.sh b/build.sh index 55086cb5..8ff80b14 100755 --- a/build.sh +++ b/build.sh @@ -16,7 +16,7 @@ BUILD_TARGET=win32 ##Do we need to create the final archive ARCHIVE_FOR_DISTRIBUTION=1 ##Which version name are we appending to the final archive -BUILD_NAME=NewUI-Beta1 +BUILD_NAME=NewUI-Beta2 TARGET_DIR=${BUILD_TARGET}-SkeinPyPy-${BUILD_NAME} ##Which versions of external programs to use