1 from __future__ import absolute_import
7 from Cura.gui import configBase
8 from Cura.gui import preview3d
9 from Cura.gui import sliceProgessPanel
10 from Cura.gui import preferencesDialog
11 from Cura.gui import dropTarget
12 from Cura.gui import printWindow
13 from Cura.util import profile
14 from Cura.util import version
15 from Cura.util import sliceRun
16 from Cura.util import meshLoader
18 class simpleModeWindow(configBase.configWindowBase):
19 "Main user interface window for Quickprint mode"
21 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
23 wx.EVT_CLOSE(self, self.OnClose)
24 #self.SetIcon(icon.getMainIcon())
26 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
28 menubar = wx.MenuBar()
30 i = fileMenu.Append(-1, 'Load model file...\tCTRL+L')
31 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
32 i = fileMenu.Append(-1, 'Prepare print...\tCTRL+R')
33 self.Bind(wx.EVT_MENU, self.OnSlice, i)
34 i = fileMenu.Append(-1, 'Print...\tCTRL+P')
35 self.Bind(wx.EVT_MENU, self.OnPrint, i)
36 fileMenu.AppendSeparator()
37 i = fileMenu.Append(-1, 'Preferences...\tCTRL+,')
38 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
39 fileMenu.AppendSeparator()
40 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
41 self.Bind(wx.EVT_MENU, self.OnQuit, i)
42 menubar.Append(fileMenu, '&File')
45 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
46 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
47 menubar.Append(toolsMenu, 'Normal mode')
50 i = helpMenu.Append(-1, 'Online documentation...')
51 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
52 i = helpMenu.Append(-1, 'Report a problem...')
53 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
54 menubar.Append(helpMenu, 'Help')
55 self.SetMenuBar(menubar)
57 if profile.getPreference('lastFile') != '':
58 self.filelist = profile.getPreference('lastFile').split(';')
59 self.SetTitle('Cura - %s - %s' % (version.getVersion(), self.filelist[-1]))
62 self.progressPanelList = []
65 self.preview3d = preview3d.previewPanel(self)
67 configPanel = wx.Panel(self)
68 printTypePanel = wx.Panel(configPanel)
69 self.printTypeNormal = wx.RadioButton(printTypePanel, -1, 'Normal quality print', style=wx.RB_GROUP)
70 self.printTypeLow = wx.RadioButton(printTypePanel, -1, 'Fast low quality print')
71 self.printTypeHigh = wx.RadioButton(printTypePanel, -1, 'High quality print')
72 self.printTypeJoris = wx.RadioButton(printTypePanel, -1, 'Thin walled cup or vase')
74 printMaterialPanel = wx.Panel(configPanel)
75 self.printMaterialPLA = wx.RadioButton(printMaterialPanel, -1, 'PLA', style=wx.RB_GROUP)
76 self.printMaterialABS = wx.RadioButton(printMaterialPanel, -1, 'ABS')
77 self.printMaterialDiameter = wx.TextCtrl(printMaterialPanel, -1, profile.getProfileSetting('filament_diameter'))
79 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
81 sizer = wx.GridBagSizer()
82 configPanel.SetSizer(sizer)
84 sb = wx.StaticBox(printTypePanel, label="Select a print type:")
85 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
86 boxsizer.Add(self.printTypeNormal)
87 boxsizer.Add(self.printTypeLow)
88 boxsizer.Add(self.printTypeHigh)
89 boxsizer.Add(self.printTypeJoris)
90 printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
91 printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
92 sizer.Add(printTypePanel, (0,0), flag=wx.EXPAND)
94 sb = wx.StaticBox(printMaterialPanel, label="Material:")
95 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
96 boxsizer.Add(self.printMaterialPLA)
97 boxsizer.Add(self.printMaterialABS)
98 boxsizer.Add(wx.StaticText(printMaterialPanel, -1, 'Diameter:'))
99 boxsizer.Add(self.printMaterialDiameter)
100 printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
101 printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
102 sizer.Add(printMaterialPanel, (1,0), flag=wx.EXPAND)
104 sb = wx.StaticBox(configPanel, label="Other:")
105 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
106 boxsizer.Add(self.printSupport)
107 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
109 # load and slice buttons.
110 loadButton = wx.Button(self, -1, '&Load model')
111 sliceButton = wx.Button(self, -1, 'P&repare print')
112 printButton = wx.Button(self, -1, '&Print')
113 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
114 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
115 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
116 #Also bind double clicking the 3D preview to load an STL file.
117 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
119 #Main sizer, to position the preview window, buttons and tab control
120 sizer = wx.GridBagSizer()
122 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
123 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
124 sizer.AddGrowableCol(2)
125 sizer.AddGrowableRow(0)
126 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
127 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
128 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
131 if len(self.filelist) > 0:
132 self.preview3d.loadModelFiles(self.filelist)
134 self.SetBackgroundColour(configPanel.GetBackgroundColour())
136 self.updateProfileToControls()
138 self.printTypeNormal.SetValue(True)
139 self.printMaterialPLA.SetValue(True)
143 self.SetMinSize(self.GetSize())
147 def OnPreferences(self, e):
148 prefDialog = preferencesDialog.preferencesDialog(self)
150 prefDialog.Show(True)
152 def OnLoadModel(self, e):
153 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
154 dlg.SetWildcard(meshLoader.wildcardFilter())
155 if dlg.ShowModal() == wx.ID_OK:
156 self.filelist = [dlg.GetPath()]
157 profile.putPreference('lastFile', ';'.join(self.filelist))
158 self.preview3d.loadModelFiles(self.filelist, True)
159 self.preview3d.setViewMode("Normal")
162 def OnDropFiles(self, filenames):
163 self.filelist = filenames
164 profile.putPreference('lastFile', ';'.join(self.filelist))
165 self.preview3d.loadModelFiles(self.filelist, True)
166 self.preview3d.setViewMode("Normal")
168 def OnSlice(self, e):
169 if len(self.filelist) < 1:
170 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
172 #save the current profile so we can put it back latter
173 oldProfile = profile.getGlobalProfileString()
175 put = profile.putProfileSetting
176 get = profile.getProfileSetting
178 put('layer_height', '0.2')
179 put('wall_thickness', '0.8')
180 put('solid_layer_thickness', '0.6')
181 put('fill_density', '20')
182 put('skirt_line_count', '1')
183 put('skirt_gap', '6.0')
184 put('print_speed', '50')
185 put('print_temperature', '220')
186 put('support', 'None')
187 put('retraction_enable', 'False')
188 put('retraction_min_travel', '5.0')
189 put('retraction_speed', '40.0')
190 put('retraction_amount', '4.5')
191 put('retraction_extra', '0.0')
192 put('travel_speed', '150')
193 put('max_z_speed', '3.0')
194 put('bottom_layer_speed', '25')
195 put('cool_min_layer_time', '10')
196 put('fan_enabled', 'True')
197 put('fan_layer', '1')
198 put('fan_speed', '100')
199 #put('model_scale', '1.0')
200 #put('flip_x', 'False')
201 #put('flip_y', 'False')
202 #put('flip_z', 'False')
203 #put('model_rotate_base', '0')
204 #put('model_multiply_x', '1')
205 #put('model_multiply_y', '1')
206 put('extra_base_wall_thickness', '0.0')
207 put('sequence', 'Loops > Perimeter > Infill')
208 put('force_first_layer_sequence', 'True')
209 put('infill_type', 'Line')
210 put('solid_top', 'True')
211 put('fill_overlap', '15')
212 put('support_rate', '50')
213 put('support_distance', '0.5')
214 put('joris', 'False')
215 put('cool_min_feedrate', '5')
216 put('bridge_speed', '100')
217 put('raft_margin', '5')
218 put('raft_base_material_amount', '100')
219 put('raft_interface_material_amount', '100')
220 put('bottom_thickness', '0.0')
222 if self.printSupport.GetValue():
223 put('support', 'Exterior Only')
225 nozzle_size = float(get('nozzle_size'))
226 if self.printTypeNormal.GetValue():
227 put('wall_thickness', nozzle_size * 2.0)
228 put('layer_height', '0.2')
229 put('fill_density', '20')
230 elif self.printTypeLow.GetValue():
231 put('wall_thickness', nozzle_size * 1.4)
232 put('layer_height', '0.25')
233 put('fill_density', '10')
234 put('print_speed', '80')
235 put('cool_min_layer_time', '3')
236 put('bottom_layer_speed', '40')
237 elif self.printTypeHigh.GetValue():
238 put('wall_thickness', nozzle_size * 2.0)
239 put('layer_height', '0.1')
240 put('fill_density', '30')
241 put('bottom_layer_speed', '15')
242 put('bottom_thickness', '0.2')
243 elif self.printTypeJoris.GetValue():
244 put('wall_thickness', nozzle_size * 1.5)
245 put('layer_height', '0.3')
246 put('solid_layer_thickness', '0.9')
247 put('fill_density', '0')
249 put('extra_base_wall_thickness', '15.0')
250 put('sequence', 'Infill > Loops > Perimeter')
251 put('force_first_layer_sequence', 'False')
252 put('solid_top', 'False')
253 put('support', 'None')
254 put('cool_min_layer_time', '3')
256 put('filament_diameter', self.printMaterialDiameter.GetValue())
257 if self.printMaterialPLA.GetValue():
258 put('filament_density', '1.00')
259 put('enable_raft', 'False')
260 put('skirt_line_count', '1')
261 if self.printMaterialABS.GetValue():
262 put('filament_density', '0.85')
263 put('enable_raft', 'True')
264 put('skirt_line_count', '0')
265 put('fan_layer', '1')
266 put('bottom_thickness', '0.0')
267 put('print_temperature', '260')
269 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
270 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
271 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
273 newSize = self.GetSize();
274 newSize.IncBy(0, spp.GetSize().GetHeight())
275 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
276 self.SetSize(newSize)
277 self.progressPanelList.append(spp)
279 #Restore the old profile.
280 profile.loadGlobalProfileFromString(oldProfile)
282 def OnPrint(self, e):
283 if len(self.filelist) < 1:
284 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
286 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
287 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
289 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
291 def OnNormalSwitch(self, e):
292 from gui import mainWindow
293 profile.putPreference('startMode', 'Normal')
294 mainWindow.mainWindow()
297 def removeSliceProgress(self, spp):
298 self.progressPanelList.remove(spp)
299 newSize = self.GetSize();
300 newSize.IncBy(0, -spp.GetSize().GetHeight())
301 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
302 self.SetSize(newSize)
304 self.sizer.Detach(spp)
305 for spp in self.progressPanelList:
306 self.sizer.Detach(spp)
308 for spp in self.progressPanelList:
309 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
316 def OnClose(self, e):
319 def updateProfileToControls(self):
320 super(simpleModeWindow, self).updateProfileToControls()
321 self.preview3d.updateProfileToControls()