From a43597ad0319e49f5b2cbef916688d15f8e5795c Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 16 Sep 2013 15:14:23 +0200 Subject: [PATCH] Add Ultimaker2 support. --- Cura/gui/configWizard.py | 45 +++++++++++++++++++++++++++------- Cura/gui/mainWindow.py | 2 +- Cura/gui/printWindow.py | 2 ++ Cura/gui/sceneView.py | 13 +++++++--- Cura/gui/simpleMode.py | 4 ++- Cura/gui/tools/youmagineGui.py | 6 ++--- Cura/util/profile.py | 5 +++- Cura/util/sliceEngine.py | 1 + 8 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Cura/gui/configWizard.py b/Cura/gui/configWizard.py index 1bafbeac..a6415977 100644 --- a/Cura/gui/configWizard.py +++ b/Cura/gui/configWizard.py @@ -264,8 +264,10 @@ class MachineSelectPage(InfoPage): super(MachineSelectPage, self).__init__(parent, "Select your machine") self.AddText('What kind of machine do you have:') - self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP) - self.UltimakerRadio.SetValue(True) + self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2", style=wx.RB_GROUP) + self.Ultimaker2Radio.SetValue(True) + self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select) + self.UltimakerRadio = self.AddRadioButton("Ultimaker") self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect) self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)") self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect) @@ -276,19 +278,36 @@ class MachineSelectPage(InfoPage): self.AddText('For full details see: http://wiki.ultimaker.com/Cura:stats') self.SubmitUserStats.SetValue(True) + def OnUltimaker2Select(self, e): + wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage) + def OnUltimakerSelect(self, e): - wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage) + wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts) def OnOtherSelect(self, e): wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage) def StoreData(self): - if self.UltimakerRadio.GetValue(): + if self.Ultimaker2Radio.GetValue(): + profile.putPreference('machine_width', '230') + profile.putPreference('machine_depth', '225') + profile.putPreference('machine_height', '205') + profile.putPreference('machine_type', 'ultimaker2') + profile.putPreference('machine_center_is_zero', 'False') + profile.putPreference('gcode_flavor', 'UltiGCode') + profile.putProfileSetting('nozzle_size', '0.4') + profile.putPreference('extruder_head_size_min_x', '75.0') + profile.putPreference('extruder_head_size_min_y', '18.0') + profile.putPreference('extruder_head_size_max_x', '18.0') + profile.putPreference('extruder_head_size_max_y', '35.0') + profile.putPreference('extruder_head_size_height', '60.0') + elif self.UltimakerRadio.GetValue(): profile.putPreference('machine_width', '205') profile.putPreference('machine_depth', '205') profile.putPreference('machine_height', '200') profile.putPreference('machine_type', 'ultimaker') profile.putPreference('machine_center_is_zero', 'False') + profile.putPreference('gcode_flavor', 'RepRap (Marlin/Sprinter)') profile.putProfileSetting('nozzle_size', '0.4') profile.putPreference('extruder_head_size_min_x', '75.0') profile.putPreference('extruder_head_size_min_y', '18.0') @@ -300,6 +319,7 @@ class MachineSelectPage(InfoPage): profile.putPreference('machine_depth', '80') profile.putPreference('machine_height', '60') profile.putPreference('machine_type', 'reprap') + profile.putPreference('gcode_flavor', 'RepRap (Marlin/Sprinter)') profile.putPreference('startMode', 'Normal') profile.putProfileSetting('nozzle_size', '0.5') profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2) @@ -335,9 +355,9 @@ class SelectParts(InfoPage): profile.putProfileSetting('retraction_enable', 'False') -class FirmwareUpgradePage(InfoPage): +class UltimakerFirmwareUpgradePage(InfoPage): def __init__(self, parent): - super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware") + super(UltimakerFirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware") self.AddText('Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work.') self.AddHiddenSeperator() self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.') @@ -367,7 +387,6 @@ class FirmwareUpgradePage(InfoPage): def OnUrlClick(self, e): webbrowser.open('http://marlinbuilder.robotfuzz.com/') - class UltimakerCheckupPage(InfoPage): def __init__(self, parent): super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup") @@ -728,6 +747,12 @@ class UltimakerCalibrateStepsPerEPage(InfoPage): def StoreData(self): profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue()) +class Ultimaker2ReadyPage(InfoPage): + def __init__(self, parent): + super(Ultimaker2ReadyPage, self).__init__(parent, "Ultimaker2") + self.AddText('Congratulations on your the purchase of your brand new Ultimaker2.') + self.AddText('Cura is now ready to be used with your Ultimaker2.') + self.AddSeperator() class configWizard(wx.wizard.Wizard): def __init__(self): @@ -739,7 +764,7 @@ class configWizard(wx.wizard.Wizard): self.firstInfoPage = FirstInfoPage(self) self.machineSelectPage = MachineSelectPage(self) self.ultimakerSelectParts = SelectParts(self) - self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self) + self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self) self.ultimakerCheckupPage = UltimakerCheckupPage(self) self.ultimakerCalibrationPage = UltimakerCalibrationPage(self) self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self) @@ -747,8 +772,10 @@ class configWizard(wx.wizard.Wizard): self.headOffsetCalibration = headOffsetCalibrationPage(self) self.repRapInfoPage = RepRapInfoPage(self) + self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self) + wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage) - wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts) + wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage) wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage) wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage) wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index da65a469..dcebc581 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -113,7 +113,7 @@ class mainWindow(wx.Frame): i = toolsMenu.Append(-1, 'Switch to full settings...') self.switchToNormalMenuItem = i self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i) - toolsMenu.AppendSeparator() + #toolsMenu.AppendSeparator() #i = toolsMenu.Append(-1, 'Batch run...') #self.Bind(wx.EVT_MENU, self.OnBatchRun, i) #self.normalModeOnlyItems.append(i) diff --git a/Cura/gui/printWindow.py b/Cura/gui/printWindow.py index e932e587..f839fff8 100644 --- a/Cura/gui/printWindow.py +++ b/Cura/gui/printWindow.py @@ -528,6 +528,8 @@ class printWindow(wx.Frame): self.machineCom.setFeedrateModifier('SUPPORT', self.supportSpeedSelect.GetValue() / 100.0) def AddTermLog(self, line): + if len(self.termLog.GetValue()) > 10000: + self.termLog.SetValue(self.termLog.GetValue()[-10000:]) self.termLog.AppendText(unicode(line, 'utf-8', 'replace')) l = len(self.termLog.GetValue()) self.termLog.SetCaret(wx.Caret(self.termLog, (l, l))) diff --git a/Cura/gui/sceneView.py b/Cura/gui/sceneView.py index 5faaba10..da35e2c0 100644 --- a/Cura/gui/sceneView.py +++ b/Cura/gui/sceneView.py @@ -409,6 +409,9 @@ class SceneView(openglGui.glGuiPanel): def OnMergeObjects(self, e): if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj: + if len(self._scene.objects()) == 2: + self._scene.merge(self._scene.objects()[0], self._scene.objects()[1]) + self.sceneUpdated() return self._scene.merge(self._selectedObj, self._focusObj) self.sceneUpdated() @@ -617,7 +620,7 @@ class SceneView(openglGui.glGuiPanel): self.Bind(wx.EVT_MENU, lambda e: self._deleteObject(self._focusObj), menu.Append(-1, 'Delete')) self.Bind(wx.EVT_MENU, self.OnMultiply, menu.Append(-1, 'Multiply')) self.Bind(wx.EVT_MENU, self.OnSplitObject, menu.Append(-1, 'Split')) - if self._selectedObj != self._focusObj and self._focusObj is not None and int(profile.getPreference('extruder_amount')) > 1: + if ((self._selectedObj != self._focusObj and self._focusObj is not None and self._selectedObj is not None) or len(self._scene.objects()) == 2) and int(profile.getPreference('extruder_amount')) > 1: self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Dual extrusion merge')) if len(self._scene.objects()) > 0: self.Bind(wx.EVT_MENU, self.OnDeleteAll, menu.Append(-1, 'Delete all')) @@ -1144,8 +1147,12 @@ void main(void) if profile.getPreference('machine_type').startswith('ultimaker'): if self._platformMesh is None: - self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker_platform.stl'))[0] - self._platformMesh._drawOffset = numpy.array([0,0,2.5], numpy.float32) + if profile.getPreference('machine_type') == 'ultimaker2': + self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker2_platform.stl'))[0] + self._platformMesh._drawOffset = numpy.array([0,-37,145], numpy.float32) + else: + self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker_platform.stl'))[0] + self._platformMesh._drawOffset = numpy.array([0,0,2.5], numpy.float32) glColor4f(1,1,1,0.5) self._objectShader.bind() self._renderObject(self._platformMesh, False, False) diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index e2f5a2b0..498993b3 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -27,6 +27,8 @@ class simpleModePanel(wx.Panel): self.printMaterialPLA = wx.RadioButton(printMaterialPanel, -1, 'PLA', style=wx.RB_GROUP) self.printMaterialABS = wx.RadioButton(printMaterialPanel, -1, 'ABS') self.printMaterialDiameter = wx.TextCtrl(printMaterialPanel, -1, profile.getProfileSetting('filament_diameter')) + if profile.getPreference('gcode_flavor') == 'UltiGCode': + printMaterialPanel.Show(False) self.printSupport = wx.CheckBox(self, -1, 'Print support structure') @@ -93,7 +95,7 @@ class simpleModePanel(wx.Panel): put('travel_speed', '150') put('max_z_speed', '3.0') put('bottom_layer_speed', '25') - put('cool_min_layer_time', '10') + put('cool_min_layer_time', '5') put('fan_enabled', 'True') put('fan_layer', '1') put('fan_speed', '100') diff --git a/Cura/gui/tools/youmagineGui.py b/Cura/gui/tools/youmagineGui.py index d62b25a7..a9104f62 100644 --- a/Cura/gui/tools/youmagineGui.py +++ b/Cura/gui/tools/youmagineGui.py @@ -262,7 +262,7 @@ class getAuthorizationWindow(wx.Frame): class newDesignWindow(wx.Frame): def __init__(self, parent, manager, ym): - super(newDesignWindow, self).__init__(parent, title='YouMagine') + super(newDesignWindow, self).__init__(parent, title='Share on YouMagine') p = wx.Panel(self) self.SetSizer(wx.BoxSizer()) self.GetSizer().Add(p, 1, wx.EXPAND) @@ -276,7 +276,7 @@ class newDesignWindow(wx.Frame): self._designLicense = wx.ComboBox(p, -1, licenseOptions[0], choices=licenseOptions, style=wx.CB_DROPDOWN|wx.CB_READONLY) self._category = wx.ComboBox(p, -1, categoryOptions[-1], choices=categoryOptions, style=wx.CB_DROPDOWN|wx.CB_READONLY) self._publish = wx.CheckBox(p, -1, 'Publish after upload') - self._shareButton = wx.Button(p, -1, 'Upload') + self._shareButton = wx.Button(p, -1, 'Share!') self._imageScroll = wx.lib.scrolledpanel.ScrolledPanel(p) self._additionalFiles = wx.CheckListBox(p, -1) self._additionalFiles.InsertItems(getAdditionalFiles(self._manager._scene.objects(), True), 0) @@ -311,7 +311,7 @@ class newDesignWindow(wx.Frame): s.Add(wx.StaticText(p, -1, 'Images:'), (6, 0), flag=wx.LEFT|wx.TOP, border=5) s.Add(self._imageScroll, (6, 1), span=(1, 2), flag=wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, border=5) s.Add(wx.StaticLine(p, -1), (7,0), span=(1,3), flag=wx.EXPAND|wx.ALL) - s.Add(wx.StaticText(p, -1, 'Design files:'), (8, 0), flag=wx.LEFT|wx.TOP, border=5) + s.Add(wx.StaticText(p, -1, 'Related design files:'), (8, 0), flag=wx.LEFT|wx.TOP, border=5) s.Add(self._additionalFiles, (8, 1), span=(1, 2), flag=wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, border=5) s.Add(wx.StaticLine(p, -1), (9,0), span=(1,3), flag=wx.EXPAND|wx.ALL) s.Add(self._shareButton, (10, 1), flag=wx.BOTTOM, border=15) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index a886f1d1..ef4240ea 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -113,7 +113,7 @@ class setting(object): ######################################################### setting('layer_height', 0.1, float, 'basic', 'Quality').setRange(0.0001).setLabel('Layer height (mm)', 'Layer height in millimeters.\nThis is the most important setting to determine the quality of your print. Normal quality prints are 0.1mm, high quality is 0.06mm. You can go up to 0.25mm with an Ultimaker for very fast prints at low quality.') setting('wall_thickness', 0.8, float, 'basic', 'Quality').setRange(0.0).setLabel('Shell thickness (mm)', 'Thickness of the outside shell in the horizontal direction.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines.') -setting('retraction_enable', False, bool, 'basic', 'Quality').setLabel('Enable retraction', 'Retract the filament when the nozzle is moving over a none-printed area. Details about the retraction can be configured in the advanced tab.') +setting('retraction_enable', False, bool, 'basic', 'Quality').setLabel('Enable retraction', 'Retract the filament when the nozzle is moving over a none-printed area.') setting('solid_layer_thickness', 0.6, float, 'basic', 'Fill').setRange(0).setLabel('Bottom/Top thickness (mm)', '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 multiple of the layer thickness makes sense. And keep it near your wall thickness to make an evenly strong part.') setting('fill_density', 20, float, 'basic', 'Fill').setRange(0, 100).setLabel('Fill Density (%)', 'This controls how densely 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.\nThis won\'t effect the outside of the print and only adjusts how strong the part becomes.') setting('nozzle_size', 0.4, float, 'advanced', 'Machine').setRange(0.1,10).setLabel('Nozzle size (mm)', '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.') @@ -481,6 +481,9 @@ def resetProfile(): putProfileSetting('nozzle_size', '0.4') if getPreference('ultimaker_extruder_upgrade') == 'True': putProfileSetting('retraction_enable', 'True') + elif getPreference('machine_type') == 'ultimaker2': + putProfileSetting('nozzle_size', '0.4') + putProfileSetting('retraction_enable', 'True') else: putProfileSetting('nozzle_size', '0.5') diff --git a/Cura/util/sliceEngine.py b/Cura/util/sliceEngine.py index 5554222f..67b1e1d2 100644 --- a/Cura/util/sliceEngine.py +++ b/Cura/util/sliceEngine.py @@ -288,6 +288,7 @@ class Slicer(object): settings['skirtDistance'] = 0 settings['skirtLineCount'] = 0 settings['raftMargin'] = int(profile.getProfileSettingFloat('raft_margin') * 1000) + settings['raftLineSpacing'] = int(profile.getProfileSettingFloat('raft_line_spacing') * 1000) settings['raftBaseThickness'] = int(profile.getProfileSettingFloat('raft_base_thickness') * 1000) settings['raftBaseLinewidth'] = int(profile.getProfileSettingFloat('raft_base_linewidth') * 1000) settings['raftInterfaceThickness'] = int(profile.getProfileSettingFloat('raft_interface_thickness') * 1000) -- 2.30.2