chiark / gitweb /
Add uppercase STL and HEX to file dialog filters for linux/MacOS
[cura.git] / Cura / cura_sf / skeinforge_application / skeinforge_plugins / craft_plugins / home.py
1 """
2 This page is in the table of contents.
3 Plugin to home the tool at beginning of each layer.
4
5 The home manual page is at:
6 http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Home
7
8 ==Operation==
9 The default 'Activate Home' checkbox is on.  When it is on, the functions described below will work, when it is off, nothing will be done.
10
11 ==Settings==
12 ===Name of Home File===
13 Default: home.gcode
14
15 At the beginning of a each layer, home will add the commands of a gcode script with the name of the "Name of Home File" setting, if one exists.  Home does not care if the text file names are capitalized, but some file systems do not handle file name cases properly, so to be on the safe side you should give them lower case names.  Home looks for those files in the alterations folder in the .skeinforge folder in the home directory. If it doesn't find the file it then looks in the alterations folder in the skeinforge_plugins folder.
16
17 ==Examples==
18 The following examples home the file Screw Holder Bottom.stl.  The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and home.py.
19
20 > python home.py
21 This brings up the home dialog.
22
23 > python home.py Screw Holder Bottom.stl
24 The home tool is parsing the file:
25 Screw Holder Bottom.stl
26 ..
27 The home tool has created the file:
28 .. Screw Holder Bottom_home.gcode
29
30 """
31
32 from __future__ import absolute_import
33 #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.
34 import __init__
35
36 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
37 from fabmetheus_utilities.vector3 import Vector3
38 from fabmetheus_utilities import archive
39 from fabmetheus_utilities import euclidean
40 from fabmetheus_utilities import gcodec
41 from fabmetheus_utilities import settings
42 from skeinforge_application.skeinforge_utilities import skeinforge_craft
43 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
44 from skeinforge_application.skeinforge_utilities import skeinforge_profile
45 import math
46 import os
47 import sys
48
49
50 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
51 __date__ = '$Date: 2008/21/04 $'
52 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
53
54
55 def getCraftedText( fileName, text, repository = None ):
56         "Home a gcode linear move file or text."
57         return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository)
58
59 def getCraftedTextFromText( gcodeText, repository = None ):
60         "Home a gcode linear move text."
61         if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'home'):
62                 return gcodeText
63         if repository == None:
64                 repository = settings.getReadRepository( HomeRepository() )
65         if not repository.activateHome.value:
66                 return gcodeText
67         return HomeSkein().getCraftedGcode(gcodeText, repository)
68
69 def getNewRepository():
70         'Get new repository.'
71         return HomeRepository()
72
73 def writeOutput(fileName, shouldAnalyze=True):
74         "Home a gcode linear move file.  Chain home the gcode if it is not already homed."
75         skeinforge_craft.writeChainTextWithNounMessage(fileName, 'home', shouldAnalyze)
76
77
78 class HomeRepository:
79         "A class to handle the home settings."
80         def __init__(self):
81                 "Set the default settings, execute title & settings fileName."
82                 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.home.html', self)
83                 self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Home', self, '')
84                 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Home')
85                 self.activateHome = settings.BooleanSetting().getFromValue('Activate Home', self, False )
86                 self.nameOfHomeFile = settings.StringSetting().getFromValue('Name of Home File:', self, 'home.gcode')
87                 self.executeTitle = 'Home'
88  
89         def execute(self):
90                 "Home button has been clicked."
91                 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
92                 for fileName in fileNames:
93                         writeOutput(fileName)
94
95
96 class HomeSkein:
97         "A class to home a skein of extrusions."
98         def __init__(self):
99                 self.distanceFeedRate = gcodec.DistanceFeedRate()
100                 self.extruderActive = False
101                 self.highestZ = None
102                 self.homeLines = []
103                 self.layerCount = settings.LayerCount()
104                 self.lineIndex = 0
105                 self.lines = None
106                 self.oldLocation = None
107                 self.shouldHome = False
108                 self.travelFeedRateMinute = 957.0
109
110         def addFloat( self, begin, end ):
111                 "Add dive to the original height."
112                 beginEndDistance = begin.distance(end)
113                 alongWay = self.absoluteEdgeWidth / beginEndDistance
114                 closeToEnd = euclidean.getIntermediateLocation( alongWay, end, begin )
115                 closeToEnd.z = self.highestZ
116                 self.distanceFeedRate.addLine( self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( self.travelFeedRateMinute, closeToEnd.dropAxis(), closeToEnd.z ) )
117
118         def addHomeTravel( self, splitLine ):
119                 "Add the home travel gcode."
120                 location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine)
121                 self.highestZ = max( self.highestZ, location.z )
122                 if not self.shouldHome:
123                         return
124                 self.shouldHome = False
125                 if self.oldLocation == None:
126                         return
127                 if self.extruderActive:
128                         self.distanceFeedRate.addLine('M103')
129                 self.addHopUp( self.oldLocation )
130                 self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.homeLines)
131                 self.addHopUp( self.oldLocation )
132                 self.addFloat( self.oldLocation, location )
133                 if self.extruderActive:
134                         self.distanceFeedRate.addLine('M101')
135
136         def addHopUp(self, location):
137                 "Add hop to highest point."
138                 locationUp = Vector3( location.x, location.y, self.highestZ )
139                 self.distanceFeedRate.addLine( self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( self.travelFeedRateMinute, locationUp.dropAxis(), locationUp.z ) )
140
141         def getCraftedGcode( self, gcodeText, repository ):
142                 "Parse gcode text and store the home gcode."
143                 self.repository = repository
144                 self.homeLines = settings.getAlterationFileLines(repository.nameOfHomeFile.value)
145                 if len(self.homeLines) < 1:
146                         return gcodeText
147                 self.lines = archive.getTextLines(gcodeText)
148                 self.parseInitialization( repository )
149                 for self.lineIndex in xrange(self.lineIndex, len(self.lines)):
150                         line = self.lines[self.lineIndex]
151                         self.parseLine(line)
152                 return self.distanceFeedRate.output.getvalue()
153
154         def parseInitialization( self, repository ):
155                 'Parse gcode initialization and store the parameters.'
156                 for self.lineIndex in xrange(len(self.lines)):
157                         line = self.lines[self.lineIndex]
158                         splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
159                         firstWord = gcodec.getFirstWord(splitLine)
160                         self.distanceFeedRate.parseSplitLine(firstWord, splitLine)
161                         if firstWord == '(</extruderInitialization>)':
162                                 self.distanceFeedRate.addTagBracketedProcedure('home')
163                                 return
164                         elif firstWord == '(<edgeWidth>':
165                                 self.absoluteEdgeWidth = abs(float(splitLine[1]))
166                         elif firstWord == '(<travelFeedRatePerSecond>':
167                                 self.travelFeedRateMinute = 60.0 * float(splitLine[1])
168                         self.distanceFeedRate.addLine(line)
169
170         def parseLine(self, line):
171                 "Parse a gcode line and add it to the bevel gcode."
172                 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
173                 if len(splitLine) < 1:
174                         return
175                 firstWord = splitLine[0]
176                 if firstWord == 'G1':
177                         self.addHomeTravel(splitLine)
178                         self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine)
179                 elif firstWord == '(<layer>':
180                         self.layerCount.printProgressIncrement('home')
181                         if len(self.homeLines) > 0:
182                                 self.shouldHome = True
183                 elif firstWord == 'M101':
184                         self.extruderActive = True
185                 elif firstWord == 'M103':
186                         self.extruderActive = False
187                 self.distanceFeedRate.addLine(line)
188
189
190 def main():
191         "Display the home dialog."
192         if len(sys.argv) > 1:
193                 writeOutput(' '.join(sys.argv[1 :]))
194         else:
195                 settings.startMainLoopFromConstructor(getNewRepository())
196
197 if __name__ == "__main__":
198         main()