From ec9f24fac877661cfb0d1bbac8fe318ef0deef56 Mon Sep 17 00:00:00 2001 From: Daid Date: Fri, 27 Apr 2012 13:45:32 +0200 Subject: [PATCH 01/30] Updates after some testing with dual extrusion (loads of work to do) --- Cura/gui/sliceProgessPanel.py | 8 +++++--- Cura/util/profile.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 3c87e22a..35367b4c 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -64,6 +64,7 @@ class sliceProgessPanel(wx.Panel): if self.filelist.index(filename) > 0: profile.putProfileSetting('fan_enabled', 'False') profile.putProfileSetting('skirt_line_count', '0') + profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_y') + 22) if len(self.filelist) > 1: profile.putProfileSetting('add_start_end_gcode', 'False') profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp') @@ -179,6 +180,7 @@ class WorkerThread(threading.Thread): files.append(open(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp', "r")) currentExtruder = 0 + resultFile.write('T%d\n' % (currentExtruder)) layerNr = -1 hasLine = True while hasLine: @@ -194,10 +196,10 @@ class WorkerThread(threading.Thread): resultFile.write(';LAYER:%d\n' % (layerNr)) resultFile.write(';EXTRUDER:%d\n' % (nextExtruder)) if nextExtruder != currentExtruder: - resultFile.write("G1 E-2 F3000\n") + resultFile.write("G1 E-5 F5000\n") resultFile.write("T%d\n" % (nextExtruder)) - resultFile.write("G1 E2 F3000\n") - resultFile.write("M92 E0\n") + resultFile.write("G1 E5 F5000\n") + resultFile.write("G92 E0\n") currentExtruder = nextExtruder layerHasLine = True resultFile.write(line) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index b6fb3ac7..419724cb 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -34,7 +34,7 @@ profileDefaultSettings = { 'bottom_layer_speed': '20', 'cool_min_layer_time': '10', 'fan_enabled': 'True', - 'fan_layer': '0', + 'fan_layer': '1', 'fan_speed': '100', 'model_scale': '1.0', 'flip_x': 'False', From b28b7adef5f4c2495310839437be0f90216777f1 Mon Sep 17 00:00:00 2001 From: Daid Date: Fri, 27 Apr 2012 13:51:27 +0200 Subject: [PATCH 02/30] Slightly increase the default machine head size because the header block can stick out. --- Cura/gui/projectPlanner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 31162255..f9e78935 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -40,8 +40,8 @@ class projectPlanner(wx.Frame): self.selection = None self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height'))) - self.headSizeMin = util3d.Vector3(70,16,0) - self.headSizeMax = util3d.Vector3(16,35,0) + self.headSizeMin = util3d.Vector3(70,18,0) + self.headSizeMax = util3d.Vector3(18,35,0) self.toolbar = toolbarUtil.Toolbar(self) From a1b4a503428829bce64902a986e1bfadaf8aea34 Mon Sep 17 00:00:00 2001 From: Daid Date: Fri, 27 Apr 2012 19:18:29 +0200 Subject: [PATCH 03/30] Added extruder selection to project planner, fixed bug with project planner where the skirt was incorrectly added to the movement size --- Cura/gui/projectPlanner.py | 56 +++++++++++++++++++++++++---------- Cura/gui/sliceProgessPanel.py | 2 +- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index f9e78935..04513bd5 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -43,6 +43,8 @@ class projectPlanner(wx.Frame): self.headSizeMin = util3d.Vector3(70,18,0) self.headSizeMax = util3d.Vector3(18,35,0) + self.extruderOffset = [util3d.Vector3(0,0,0), util3d.Vector3(-22,0,0), util3d.Vector3(0,0,0), util3d.Vector3(0,0,0)] + self.toolbar = toolbarUtil.Toolbar(self) toolbarUtil.NormalButton(self.toolbar, self.OnLoadProject, 'open.png', 'Open project') @@ -95,6 +97,12 @@ class projectPlanner(wx.Frame): sizer.Add(self.scaleCtrl, (0,1), flag=wx.ALIGN_BOTTOM|wx.EXPAND) sizer.Add(wx.StaticText(panel, -1, 'Rotate'), (1,0), flag=wx.ALIGN_CENTER_VERTICAL) sizer.Add(self.rotateCtrl, (1,1), flag=wx.ALIGN_BOTTOM|wx.EXPAND) + + if int(profile.getPreference('extruder_amount')) > 1: + self.extruderCtrl = wx.ComboBox(panel, -1, '1', choices=map(str, range(1, int(profile.getPreference('extruder_amount'))+1)), style=wx.CB_DROPDOWN|wx.CB_READONLY) + sizer.Add(wx.StaticText(panel, -1, 'Extruder'), (2,0), flag=wx.ALIGN_CENTER_VERTICAL) + sizer.Add(self.extruderCtrl, (2,1), flag=wx.ALIGN_BOTTOM|wx.EXPAND) + self.extruderCtrl.Bind(wx.EVT_COMBOBOX, self.OnExtruderChange) self.scaleCtrl.Bind(wx.EVT_TEXT, self.OnScaleChange) self.rotateCtrl.Bind(wx.EVT_SPINCTRL, self.OnRotateChange) @@ -126,6 +134,7 @@ class projectPlanner(wx.Frame): cp.set(section, 'flipZ', str(item.flipZ)) cp.set(section, 'swapXZ', str(item.swapXZ)) cp.set(section, 'swapYZ', str(item.swapYZ)) + cp.set(section, 'extruder', str(item.extruder+1)) i += 1 cp.write(open(dlg.GetPath(), "w")) dlg.Destroy() @@ -149,11 +158,12 @@ class projectPlanner(wx.Frame): item.centerY = float(cp.get(section, 'centerY')) item.scale = float(cp.get(section, 'scale')) item.rotate = float(cp.get(section, 'rotate')) - cp.get(section, 'flipX') - cp.get(section, 'flipY') - cp.get(section, 'flipZ') - cp.get(section, 'swapXZ') - cp.get(section, 'swapYZ') + item.flipX = cp.get(section, 'flipX') == 'True' + item.flipY = cp.get(section, 'flipY') == 'True' + item.flipZ = cp.get(section, 'flipZ') == 'True' + item.swapXZ = cp.get(section, 'swapXZ') == 'True' + item.swapYZ = cp.get(section, 'swapYZ') == 'True' + item.extuder = int(cp.get(section, 'extruder'))-1 i += 1 self.list.append(item) @@ -184,8 +194,10 @@ class projectPlanner(wx.Frame): self.selection = self.list[self.listbox.GetSelection()] self.scaleCtrl.SetValue(str(self.selection.scale)) self.rotateCtrl.SetValue(int(self.selection.rotate)) + if int(profile.getPreference('extruder_amount')) > 1: + self.extruderCtrl.SetValue(str(self.selection.extruder+1)) self.preview.Refresh() - + def OnAddModel(self, e): dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST|wx.FD_MULTIPLE) dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") @@ -233,7 +245,7 @@ class projectPlanner(wx.Frame): extraSizeMax = self.headSizeMax if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') - extraSizeMin = extraSizeMin - util3d.Vector3(skirtSize, skirtSize, 0) + extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0) posX = self.machineSize.x @@ -281,8 +293,8 @@ class projectPlanner(wx.Frame): clearZ = 0 actionList = [] for item in self.list: - put('machine_center_x', item.centerX) - put('machine_center_y', item.centerY) + put('machine_center_x', item.centerX - self.extruderOffset[item.extruder].x) + put('machine_center_y', item.centerY - self.extruderOffset[item.extruder].y) put('model_scale', item.scale) put('flip_x', item.flipX) put('flip_y', item.flipY) @@ -295,6 +307,7 @@ class projectPlanner(wx.Frame): action.sliceCmd = sliceRun.getSliceCommand(item.filename) action.centerX = item.centerX action.centerY = item.centerY + action.extruder = item.extruder action.filename = item.filename clearZ = max(clearZ, item.getMaximum().z * item.scale) action.clearZ = clearZ @@ -312,6 +325,7 @@ class projectPlanner(wx.Frame): dlg.Destroy() pspw = ProjectSliceProgressWindow(actionList, resultFilename) + pspw.extruderOffset = self.extruderOffset pspw.Centre() pspw.Show(True) @@ -331,6 +345,7 @@ class projectPlanner(wx.Frame): item.flipZ = False item.swapXZ = False item.swapYZ = False + item.extruder = 0 item.modelDisplayList = None item.modelDirty = False @@ -355,6 +370,12 @@ class projectPlanner(wx.Frame): self.selection.rotate = float(self.rotateCtrl.GetValue()) self.updateModelTransform(self.selection) + def OnExtruderChange(self, e): + if self.selection == None: + return + self.selection.extruder = int(self.extruderCtrl.GetValue()) - 1 + self.preview.Refresh() + def updateModelTransform(self, item): rotate = item.rotate / 180.0 * math.pi scaleX = 1.0 @@ -508,7 +529,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): extraSizeMax = self.parent.headSizeMax if profile.getProfileSettingFloat('skirt_line_count') > 0: skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') - extraSizeMin = extraSizeMin - util3d.Vector3(skirtSize, skirtSize, 0) + extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0) for item in self.parent.list: @@ -517,8 +538,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas): for idx1 in xrange(0, len(self.parent.list)): item = self.parent.list[idx1] - iMin1 = item.getMinimum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) - extraSizeMin - iMax1 = item.getMaximum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) + extraSizeMax + iMin1 = item.getMinimum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) - extraSizeMin - self.parent.extruderOffset[item.extruder] + iMax1 = item.getMaximum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) + extraSizeMax - self.parent.extruderOffset[item.extruder] for idx2 in xrange(0, idx1): item2 = self.parent.list[idx2] iMin2 = item2.getMinimum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0) @@ -566,8 +587,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas): vMin = item.getMinimum() * item.scale vMax = item.getMaximum() * item.scale - vMinHead = vMin - extraSizeMin - vMaxHead = vMax + extraSizeMax + vMinHead = vMin - extraSizeMin - self.parent.extruderOffset[item.extruder] + vMaxHead = vMax + extraSizeMax - self.parent.extruderOffset[item.extruder] glDisable(GL_LIGHTING) @@ -702,12 +723,15 @@ class ProjectSliceProgressWindow(wx.Frame): self.returnCode = p.wait() oldProfile = profile.getGlobalProfileString() - put('machine_center_x', action.centerX) - put('machine_center_y', action.centerY) + put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x) + put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y) put('clear_z', action.clearZ) + put('extruder', action.extruder) if action == self.actionList[0]: resultFile.write(';TYPE:CUSTOM\n') + resultFile.write('T%d\n' % (action.extruder)) + currentExtruder = action.extruder resultFile.write(profile.getAlterationFileContents('start.gcode')) else: #reset the extrusion length, and move to the next object center. diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 35367b4c..5923693e 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -64,7 +64,7 @@ class sliceProgessPanel(wx.Panel): if self.filelist.index(filename) > 0: profile.putProfileSetting('fan_enabled', 'False') profile.putProfileSetting('skirt_line_count', '0') - profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_y') + 22) + profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') + 22) if len(self.filelist) > 1: profile.putProfileSetting('add_start_end_gcode', 'False') profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp') From 4a57502535bb7f7c29a39f5ff52cef4f1ff258af Mon Sep 17 00:00:00 2001 From: Daid Date: Fri, 27 Apr 2012 21:48:56 +0200 Subject: [PATCH 04/30] backwards compatibility with older project files. --- Cura/gui/projectPlanner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 04513bd5..538ea47c 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -163,7 +163,8 @@ class projectPlanner(wx.Frame): item.flipZ = cp.get(section, 'flipZ') == 'True' item.swapXZ = cp.get(section, 'swapXZ') == 'True' item.swapYZ = cp.get(section, 'swapYZ') == 'True' - item.extuder = int(cp.get(section, 'extruder'))-1 + if cp.has_option(section, 'extruder'): + item.extuder = int(cp.get(section, 'extruder'))-1 i += 1 self.list.append(item) From be075e5e18e7213935ce63242de7883c61563bce Mon Sep 17 00:00:00 2001 From: Ferdi van der Werf Date: Sat, 28 Apr 2012 08:02:20 +0200 Subject: [PATCH 05/30] Fixes #80 Corrected function call and adjusted parameters accordingly. --- Cura/gui/simpleMode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index f49f1e0a..4f38ca95 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -117,7 +117,7 @@ class simpleModeWindow(configBase.configWindowBase): self.sizer = sizer if self.filename != "None": - self.preview3d.loadModelFile(self.filename) + self.preview3d.loadModelFiles([self.filename]) self.lastPath = os.path.split(self.filename)[0] self.updateProfileToControls() @@ -158,7 +158,7 @@ class simpleModeWindow(configBase.configWindowBase): if not(os.path.exists(self.filename)): return self.lastPath = os.path.split(self.filename)[0] - self.preview3d.loadModelFile(self.filename) + self.preview3d.loadModelFiles([self.filename]) self.preview3d.setViewMode("Normal") dlg.Destroy() From ffb6b42d5da48733179ffdf71d8eecdd9292c563 Mon Sep 17 00:00:00 2001 From: Daid Date: Sat, 28 Apr 2012 18:32:34 +0200 Subject: [PATCH 06/30] Fixed #82 --- Cura/util/profile.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 419724cb..b7450a6c 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -177,10 +177,12 @@ def getGlobalProfileString(): p = [] alt = [] - for key in globalProfileParser.options('profile'): - p.append(key + "=" + globalProfileParser.get('profile', key)) - for key in globalProfileParser.options('alterations'): - alt.append(key + "=" + globalProfileParser.get('alterations', key)) + if globalProfileParser.has_section('profile'): + for key in globalProfileParser.options('profile'): + p.append(key + "=" + globalProfileParser.get('profile', key)) + if globalProfileParser.has_section('alterations'): + for key in globalProfileParser.options('alterations'): + alt.append(key + "=" + globalProfileParser.get('alterations', key)) ret = '\b'.join(p) + '\f' + '\b'.join(alt) ret = base64.b64encode(zlib.compress(ret, 9)) return ret From 9c91c58c6e6cab99f4c854643c7d1acee5650fa6 Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 29 Apr 2012 11:35:36 +0200 Subject: [PATCH 07/30] Move extruder offset and extruder head size to preferences. --- Cura/gui/preferencesDialog.py | 16 ++++++++++++++++ Cura/gui/projectPlanner.py | 26 +++++++++++++++----------- Cura/gui/sliceProgessPanel.py | 9 ++++++--- Cura/util/profile.py | 11 +++++++++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/Cura/gui/preferencesDialog.py b/Cura/gui/preferencesDialog.py index ec315979..41bded92 100644 --- a/Cura/gui/preferencesDialog.py +++ b/Cura/gui/preferencesDialog.py @@ -7,6 +7,7 @@ import ConfigParser from gui import configBase from gui import validators from gui import machineCom +from util import profile class preferencesDialog(configBase.configWindowBase): def __init__(self, parent): @@ -14,6 +15,8 @@ class preferencesDialog(configBase.configWindowBase): wx.EVT_CLOSE(self, self.OnClose) + self.oldExtruderAmount = int(profile.getPreference('extruder_amount')) + left, right, main = self.CreateConfigPanel(self) configBase.TitleRow(left, 'Machine settings') c = configBase.SettingRow(left, 'Steps per E', 'steps_per_e', '0', 'Amount of steps per mm filament extrusion', type = 'preference') @@ -25,6 +28,13 @@ class preferencesDialog(configBase.configWindowBase): c = configBase.SettingRow(left, 'Machine height (mm)', 'machine_height', '200', 'Size of the machine in mm', type = 'preference') validators.validFloat(c, 10.0) c = configBase.SettingRow(left, 'Extruder count', 'extruder_amount', ['1', '2', '3', '4'], 'Amount of extruders in your machine.', type = 'preference') + + for i in xrange(1, self.oldExtruderAmount): + configBase.TitleRow(left, 'Extruder %d' % (i+1)) + c = configBase.SettingRow(left, 'Offset X', 'extruder_offset_x%d' % (i), '0.0', 'The offset of your secondary extruder compared to the primary.', type = 'preference') + validators.validFloat(c) + c = configBase.SettingRow(left, 'Offset Y', 'extruder_offset_y%d' % (i), '0.0', 'The offset of your secondary extruder compared to the primary.', type = 'preference') + validators.validFloat(c) configBase.TitleRow(left, 'Filament settings') c = configBase.SettingRow(left, 'Filament density (kg/m3)', 'filament_density', '1300', 'Weight of the filament per m3. Around 1300 for PLA. And around 1040 for ABS. This value is used to estimate the weight if the filament used for the print.', type = 'preference') @@ -42,10 +52,16 @@ class preferencesDialog(configBase.configWindowBase): #c = configBase.SettingRow(left, 'Slicer selection', 'slicer', ['Cura (Skeinforge based)', 'Slic3r'], 'Which slicer to use to slice objects. Usually the Cura engine produces the best results. But Slic3r is developing fast and is faster with slicing.', type = 'preference') c = configBase.SettingRow(left, 'Save profile on slice', 'save_profile', False, 'When slicing save the profile as [stl_file]_profile.ini next to the model.', type = 'preference') + self.okButton = wx.Button(left, -1, 'Ok') + left.GetSizer().Add(self.okButton, (left.GetSizer().GetRows(), 1)) + self.okButton.Bind(wx.EVT_BUTTON, self.OnClose) + self.MakeModal(True) main.Fit() self.Fit() def OnClose(self, e): + if self.oldExtruderAmount != int(profile.getPreference('extruder_amount')): + wx.MessageBox('After changing the amount of extruders you need to restart Cura for full effect.', 'Extruder amount warning.', wx.OK | wx.ICON_INFORMATION) self.MakeModal(False) self.Destroy() diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 538ea47c..448b31b2 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -40,10 +40,14 @@ class projectPlanner(wx.Frame): self.selection = None self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height'))) - self.headSizeMin = util3d.Vector3(70,18,0) - self.headSizeMax = util3d.Vector3(18,35,0) + self.headSizeMin = util3d.Vector3(float(profile.getPreference('extruder_head_size_min_x')), float(profile.getPreference('extruder_head_size_min_y')),0) + self.headSizeMax = util3d.Vector3(float(profile.getPreference('extruder_head_size_max_x')), float(profile.getPreference('extruder_head_size_max_y')),0) - self.extruderOffset = [util3d.Vector3(0,0,0), util3d.Vector3(-22,0,0), util3d.Vector3(0,0,0), util3d.Vector3(0,0,0)] + self.extruderOffset = [ + util3d.Vector3(0,0,0), + util3d.Vector3(float(profile.getPreference('extruder_offset_x1')), float(profile.getPreference('extruder_offset_y1')), 0), + util3d.Vector3(float(profile.getPreference('extruder_offset_x2')), float(profile.getPreference('extruder_offset_y2')), 0), + util3d.Vector3(float(profile.getPreference('extruder_offset_x3')), float(profile.getPreference('extruder_offset_y3')), 0)] self.toolbar = toolbarUtil.Toolbar(self) @@ -467,14 +471,14 @@ class PreviewGLCanvas(glcanvas.GLCanvas): if item != None: item.centerX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2 item.centerY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2 - if item.centerX < -item.getMinimum().x * item.scale: - item.centerX = -item.getMinimum().x * item.scale - if item.centerY < -item.getMinimum().y * item.scale: - item.centerY = -item.getMinimum().y * item.scale - if item.centerX > self.parent.machineSize.x - item.getMaximum().x * item.scale: - item.centerX = self.parent.machineSize.x - item.getMaximum().x * item.scale - if item.centerY > self.parent.machineSize.y - item.getMaximum().y * item.scale: - item.centerY = self.parent.machineSize.y - item.getMaximum().y * item.scale + if item.centerX < -item.getMinimum().x * item.scale + self.parent.extruderOffset[item.extruder].x: + item.centerX = -item.getMinimum().x * item.scale + self.parent.extruderOffset[item.extruder].x + if item.centerY < -item.getMinimum().y * item.scale + self.parent.extruderOffset[item.extruder].y: + item.centerY = -item.getMinimum().y * item.scale + self.parent.extruderOffset[item.extruder].y + if item.centerX > self.parent.machineSize.x + self.parent.extruderOffset[item.extruder].x - item.getMaximum().x * item.scale: + item.centerX = self.parent.machineSize.x + self.parent.extruderOffset[item.extruder].x - item.getMaximum().x * item.scale + if item.centerY > self.parent.machineSize.y + self.parent.extruderOffset[item.extruder].y - item.getMaximum().y * item.scale: + item.centerY = self.parent.machineSize.y + self.parent.extruderOffset[item.extruder].y - item.getMaximum().y * item.scale self.Refresh() else: self.allowDrag = False diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 5923693e..b56fc5ed 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -60,11 +60,13 @@ class sliceProgessPanel(wx.Panel): cmdList = [] oldProfile = profile.getGlobalProfileString() for filename in self.filelist: - print filename, self.filelist.index(filename) - if self.filelist.index(filename) > 0: + idx = self.filelist.index(filename) + print filename, idx + if idx > 0: profile.putProfileSetting('fan_enabled', 'False') profile.putProfileSetting('skirt_line_count', '0') - profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') + 22) + profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') + float(profile.getPreference('extruder_offset_x%d' % (idx)))) + profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') + float(profile.getPreference('extruder_offset_y%d' % (idx)))) if len(self.filelist) > 1: profile.putProfileSetting('add_start_end_gcode', 'False') profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp') @@ -197,6 +199,7 @@ class WorkerThread(threading.Thread): resultFile.write(';EXTRUDER:%d\n' % (nextExtruder)) if nextExtruder != currentExtruder: resultFile.write("G1 E-5 F5000\n") + resultFile.write("G92 E0\n") resultFile.write("T%d\n" % (nextExtruder)) resultFile.write("G1 E5 F5000\n") resultFile.write("G92 E0\n") diff --git a/Cura/util/profile.py b/Cura/util/profile.py index b7450a6c..046617cb 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -128,6 +128,12 @@ preferencesDefaultSettings = { 'machine_depth': '205', 'machine_height': '200', 'extruder_amount': '1', + 'extruder_offset_x1': '-22.0', + 'extruder_offset_y1': '0.0', + 'extruder_offset_x2': '0.0', + 'extruder_offset_y2': '0.0', + 'extruder_offset_x3': '0.0', + 'extruder_offset_y3': '0.0', 'filament_density': '1300', 'steps_per_e': '0', 'serial_port': 'AUTO', @@ -136,6 +142,11 @@ preferencesDefaultSettings = { 'save_profile': 'False', 'filament_cost_kg': '0', 'filament_cost_meter': '0', + + 'extruder_head_size_min_x': '70.0', + 'extruder_head_size_min_y': '18.0', + 'extruder_head_size_max_x': '18.0', + 'extruder_head_size_max_y': '35.0', } ######################################################### From 2e6f8874999f897d72450f0ecaf2901a3c993681 Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 29 Apr 2012 11:44:07 +0200 Subject: [PATCH 08/30] Remove other models when loading a single model again after a dual load. --- Cura/gui/preview3d.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index ac8eff97..ad2f5f0d 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -203,8 +203,9 @@ class previewPanel(wx.Panel): def loadModelFiles(self, filelist): while len(filelist) > len(self.objectList): self.objectList.append(previewObject()) - for idx in xrange(len(self.objectList), len(filelist)): + for idx in xrange(len(filelist), len(self.objectList)): self.objectList[idx].mesh = None + self.objectList[idx].filename = None for idx in xrange(0, len(filelist)): obj = self.objectList[idx] if obj.filename != filelist[idx]: @@ -232,7 +233,7 @@ class previewPanel(wx.Panel): def doFileLoadThread(self): for obj in self.objectList: - if os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime: + if obj.filename != None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime: obj.ileTime = os.stat(obj.filename).st_mtime mesh = stl.stlModel() mesh.load(obj.filename) From 632a4475751fdbe2cba42598ba03e312659f8a3f Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 29 Apr 2012 12:00:13 +0200 Subject: [PATCH 09/30] Show print time, filemant used and cost estimate after slicing. --- Cura/gui/printWindow.py | 11 +++-------- Cura/gui/sliceProgessPanel.py | 10 +++++++++- Cura/util/gcodeInterpreter.py | 15 +++++++++++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Cura/gui/printWindow.py b/Cura/gui/printWindow.py index 195b5942..5f68556d 100644 --- a/Cura/gui/printWindow.py +++ b/Cura/gui/printWindow.py @@ -176,14 +176,9 @@ class printWindow(wx.Frame): status = "" if self.gcode != None: status += "Filament: %.2fm %.2fg\n" % (self.gcode.extrusionAmount / 1000, self.gcode.calculateWeight() * 1000) - cost_kg = float(profile.getPreference('filament_cost_kg')) - cost_meter = float(profile.getPreference('filament_cost_meter')) - if cost_kg > 0.0 and cost_meter > 0.0: - status += "Filament cost: %.2f / %.2f\n" % (self.gcode.calculateWeight() * cost_kg, self.gcode.extrusionAmount / 1000 * cost_meter) - elif cost_kg > 0.0: - status += "Filament cost: %.2f\n" % (self.gcode.calculateWeight() * cost_kg) - elif cost_meter > 0.0: - status += "Filament cost: %.2f\n" % (self.gcode.extrusionAmount / 1000 * cost_meter) + cost = self.gcode.calculateCost() + if cost != False: + status += "Filament cost: %s\n" % (cost) status += "Print time: %02d:%02d\n" % (int(self.gcode.totalMoveTimeMinute / 60), int(self.gcode.totalMoveTimeMinute % 60)) if self.printIdx == None: self.progress.SetValue(0) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index b56fc5ed..c28e2cb8 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -6,6 +6,7 @@ import wx, sys, os, math, threading, subprocess, time from util import profile from util import sliceRun from util import exporer +from util import gcodeInterpreter class sliceProgessPanel(wx.Panel): def __init__(self, mainWindow, parent, filelist): @@ -100,7 +101,12 @@ class sliceProgessPanel(wx.Panel): self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton) self.sizer.Add(self.logButton, 0) if result.returnCode == 0: - self.statusText.SetLabel("Ready.") + status = "Ready: Filament: %.2fm %.2fg" % (result.gcode.extrusionAmount / 1000, result.gcode.calculateWeight() * 1000) + status += " Print time: %02d:%02d\n" % (int(result.gcode.totalMoveTimeMinute / 60), int(result.gcode.totalMoveTimeMinute % 60)) + cost = result.gcode.calculateCost() + if cost != False: + status += "Cost: %s\n" % (cost) + self.statusText.SetLabel(status) if exporer.hasExporer(): self.openFileLocationButton = wx.Button(self, -1, "Open file location") self.Bind(wx.EVT_BUTTON, self.OnOpenFileLocation, self.openFileLocationButton) @@ -169,6 +175,8 @@ class WorkerThread(threading.Thread): if self.fileIdx == len(self.cmdList): if len(self.filelist) > 1: self._stitchMultiExtruder() + self.gcode = gcodeInterpreter.gcode() + self.gcode.load(self.filelist[0][:self.filelist[0].rfind('.')]+'_export.gcode') wx.CallAfter(self.notifyWindow.OnSliceDone, self) else: self.run() diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 0518be27..7e83d3f4 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -38,6 +38,17 @@ class gcode(): volumeM3 = (self.extrusionAmount * (math.pi * radius * radius)) / (1000*1000*1000) return volumeM3 * float(profile.getPreference('filament_density')) + def calculateCost(self): + cost_kg = float(profile.getPreference('filament_cost_kg')) + cost_meter = float(profile.getPreference('filament_cost_meter')) + if cost_kg > 0.0 and cost_meter > 0.0: + return "%.2f / %.2f" % (self.calculateWeight() * cost_kg, self.extrusionAmount / 1000 * cost_meter) + elif cost_kg > 0.0: + return "%.2f" % (self.calculateWeight() * cost_kg) + elif cost_meter > 0.0: + return "%.2f" % (self.extrusionAmount / 1000 * cost_meter) + return False + def _load(self, gcodeFile): filePos = 0 pos = util3d.Vector3() @@ -200,8 +211,8 @@ class gcode(): self.layerList.append(currentLayer) self.extrusionAmount = maxExtrusion self.totalMoveTimeMinute = totalMoveTimeMinute - print "Extruded a total of: %d mm of filament" % (self.extrusionAmount) - print "Estimated print duration: %.2f minutes" % (self.totalMoveTimeMinute) + #print "Extruded a total of: %d mm of filament" % (self.extrusionAmount) + #print "Estimated print duration: %.2f minutes" % (self.totalMoveTimeMinute) def getCodeInt(self, line, code): if code not in self.regMatch: From 70d833b19d7048f4600facb6fa8a6f3760c0fbba Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 29 Apr 2012 12:01:56 +0200 Subject: [PATCH 10/30] No newlines in slice progress status label. --- Cura/gui/sliceProgessPanel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index c28e2cb8..7c1a2df0 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -102,10 +102,10 @@ class sliceProgessPanel(wx.Panel): self.sizer.Add(self.logButton, 0) if result.returnCode == 0: status = "Ready: Filament: %.2fm %.2fg" % (result.gcode.extrusionAmount / 1000, result.gcode.calculateWeight() * 1000) - status += " Print time: %02d:%02d\n" % (int(result.gcode.totalMoveTimeMinute / 60), int(result.gcode.totalMoveTimeMinute % 60)) + status += " Print time: %02d:%02d" % (int(result.gcode.totalMoveTimeMinute / 60), int(result.gcode.totalMoveTimeMinute % 60)) cost = result.gcode.calculateCost() if cost != False: - status += "Cost: %s\n" % (cost) + status += "Cost: %s" % (cost) self.statusText.SetLabel(status) if exporer.hasExporer(): self.openFileLocationButton = wx.Button(self, -1, "Open file location") From 74d8329a73a87a2029fb122e1dde0d8b07bd93f8 Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 29 Apr 2012 14:22:20 +0200 Subject: [PATCH 11/30] Fixed positioning when using multiple extruders. Fixed GCode preview for multiple extruders. Removed multiply, depricated because of the project planner, and does not work right with multiple extruders. --- .../geometry/solids/triangle_mesh.py | 2 +- Cura/cura_sf/fabmetheus_utilities/settings.py | 5 ++- .../skeinforge_plugins/craft_plugins/carve.py | 41 ++++++++++++++----- .../skeinforge_plugins/craft_plugins/skirt.py | 2 + Cura/gui/preview3d.py | 15 ++++--- Cura/gui/sliceProgessPanel.py | 3 +- Cura/util/gcodeInterpreter.py | 16 ++++++-- 7 files changed, 60 insertions(+), 24 deletions(-) diff --git a/Cura/cura_sf/fabmetheus_utilities/geometry/solids/triangle_mesh.py b/Cura/cura_sf/fabmetheus_utilities/geometry/solids/triangle_mesh.py index 32398305..550f4006 100644 --- a/Cura/cura_sf/fabmetheus_utilities/geometry/solids/triangle_mesh.py +++ b/Cura/cura_sf/fabmetheus_utilities/geometry/solids/triangle_mesh.py @@ -824,7 +824,7 @@ class TriangleMesh( group.Group ): halfHeight = 0.5 * self.layerHeight self.zoneArrangement = ZoneArrangement(self.layerHeight, self.getTransformedVertexes()) layerTop = self.cornerMaximum.z - halfHeight * 0.5 - z = self.cornerMinimum.z + halfHeight + z = halfHeight layerCount = int((layerTop - z) / self.layerHeight) + 1 while z < layerTop: getLoopLayerAppend(self.loopLayers, layerCount, z).loops = self.getLoopsFromMesh(self.zoneArrangement.getEmptyZ(z)) diff --git a/Cura/cura_sf/fabmetheus_utilities/settings.py b/Cura/cura_sf/fabmetheus_utilities/settings.py index 08ad268d..fa79a29c 100644 --- a/Cura/cura_sf/fabmetheus_utilities/settings.py +++ b/Cura/cura_sf/fabmetheus_utilities/settings.py @@ -113,6 +113,9 @@ def getProfileInformation(): 'SwapYZ': storedSetting("swap_yz"), 'Scale': storedSettingFloat("model_scale"), 'Rotate': storedSettingFloat("model_rotate_base"), + 'CenterX': storedSettingFloat("machine_center_x"), + 'CenterY': storedSettingFloat("machine_center_y"), + 'AlternativeCenterFile': storedSetting("alternative_center"), },'scale': { 'Activate_Scale': "False", 'XY_Plane_Scale_ratio': DEFSET, @@ -171,7 +174,7 @@ def getProfileInformation(): 'Surrounding_Angle_degrees': DEFSET, 'Thread_Sequence_Choice': storedSetting('sequence'), },'multiply': { - 'Activate_Multiply': "True", + 'Activate_Multiply': "False", 'Center_X_mm': storedSettingFloat("machine_center_x"), 'Center_Y_mm': storedSettingFloat("machine_center_y"), 'Number_of_Columns_integer': storedSetting('model_multiply_x'), diff --git a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py index ae949b3d..b3ad845e 100644 --- a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py +++ b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py @@ -185,8 +185,11 @@ class CarveRepository: self.flipZ = settings.BooleanSetting().getFromValue('FlipZ', self, False) self.swapXZ = settings.BooleanSetting().getFromValue('SwapXZ', self, False) self.swapYZ = settings.BooleanSetting().getFromValue('SwapYZ', self, False) + self.centerX = settings.FloatSpin().getFromValue(0.0, 'CenterX', self, 1000.0, 0.0) + self.centerY = settings.FloatSpin().getFromValue(0.0, 'CenterY', self, 1000.0, 0.0) self.scale = settings.FloatSpin().getFromValue( 0.1, 'Scale', self, 10.0, 1.0 ) self.rotate = settings.FloatSpin().getFromValue( -180.0, 'Rotate', self, 180.0, 0.0 ) + self.alternativeCenter = settings.StringSetting().getFromValue('AlternativeCenterFile', self, '') def execute(self): @@ -219,16 +222,6 @@ class CarveSkein: mat10 = math.sin(rotate) * scaleX mat11 = math.cos(rotate) * scaleY - minZ = carving.getMinimumZ() - minSize = carving.getCarveCornerMinimum() - maxSize = carving.getCarveCornerMaximum() - for v in carving.vertexes: - v.z -= minZ - v.x -= minSize.x + (maxSize.x - minSize.x) / 2 - v.y -= minSize.y + (maxSize.y - minSize.y) / 2 - #v.x += self.machineCenter.x - #v.y += self.machineCenter.y - for i in xrange(0, len(carving.vertexes)): x = carving.vertexes[i].x y = carving.vertexes[i].y @@ -242,6 +235,34 @@ class CarveSkein: x * mat10 + y * mat11, z * scaleZ) + if repository.alternativeCenter.value != '': + carving2 = svg_writer.getCarving(repository.alternativeCenter.value) + for i in xrange(0, len(carving2.vertexes)): + x = carving2.vertexes[i].x + y = carving2.vertexes[i].y + z = carving2.vertexes[i].z + if swapXZ: + x, z = z, x + if swapYZ: + y, z = z, y + carving2.vertexes[i] = Vector3( + x * mat00 + y * mat01, + x * mat10 + y * mat11, + z * scaleZ) + minZ = carving2.getMinimumZ() + minSize = carving2.getCarveCornerMinimum() + maxSize = carving2.getCarveCornerMaximum() + else: + minZ = carving.getMinimumZ() + minSize = carving.getCarveCornerMinimum() + maxSize = carving.getCarveCornerMaximum() + for v in carving.vertexes: + v.z -= minZ + v.x -= minSize.x + (maxSize.x - minSize.x) / 2 + v.y -= minSize.y + (maxSize.y - minSize.y) / 2 + v.x += repository.centerX.value + v.y += repository.centerY.value + layerHeight = repository.layerHeight.value edgeWidth = repository.edgeWidth.value carving.setCarveLayerHeight(layerHeight) diff --git a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py index 4a87d471..51f3549c 100644 --- a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py +++ b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py @@ -171,6 +171,8 @@ class SkirtSkein: def addSkirt(self, z): 'At skirt at z to gcode output.' + if len(self.outsetLoops) < 1 or len(self.outsetLoops[0]) < 1: + return self.setSkirtFeedFlowTemperature() self.distanceFeedRate.addLine('()') oldTemperature = self.oldTemperatureInput diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index ad2f5f0d..f905d0f4 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -93,12 +93,11 @@ class previewPanel(wx.Panel): self.toolbar2.AddSeparator() # Multiply - self.mulXadd = toolbarUtil.NormalButton(self.toolbar2, self.OnMulXAddClick, 'object-mul-x-add.png', 'Increase number of models on X axis') - self.mulXsub = toolbarUtil.NormalButton(self.toolbar2, self.OnMulXSubClick, 'object-mul-x-sub.png', 'Decrease number of models on X axis') - self.mulYadd = toolbarUtil.NormalButton(self.toolbar2, self.OnMulYAddClick, 'object-mul-y-add.png', 'Increase number of models on Y axis') - self.mulYsub = toolbarUtil.NormalButton(self.toolbar2, self.OnMulYSubClick, 'object-mul-y-sub.png', 'Decrease number of models on Y axis') - - self.toolbar2.AddSeparator() + #self.mulXadd = toolbarUtil.NormalButton(self.toolbar2, self.OnMulXAddClick, 'object-mul-x-add.png', 'Increase number of models on X axis') + #self.mulXsub = toolbarUtil.NormalButton(self.toolbar2, self.OnMulXSubClick, 'object-mul-x-sub.png', 'Decrease number of models on X axis') + #self.mulYadd = toolbarUtil.NormalButton(self.toolbar2, self.OnMulYAddClick, 'object-mul-y-add.png', 'Increase number of models on Y axis') + #self.mulYsub = toolbarUtil.NormalButton(self.toolbar2, self.OnMulYSubClick, 'object-mul-y-sub.png', 'Decrease number of models on Y axis') + #self.toolbar2.AddSeparator() # Rotate self.rotateReset = toolbarUtil.NormalButton(self.toolbar2, self.OnRotateReset, 'object-rotate.png', 'Reset model rotation') @@ -623,8 +622,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glFlush() def drawModel(self, obj): - multiX = int(profile.getProfileSetting('model_multiply_x')) - multiY = int(profile.getProfileSetting('model_multiply_y')) + multiX = 1 #int(profile.getProfileSetting('model_multiply_x')) + multiY = 1 #int(profile.getProfileSetting('model_multiply_y')) modelScale = profile.getProfileSettingFloat('model_scale') modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale glPushMatrix() diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 7c1a2df0..bb83266b 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -68,6 +68,7 @@ class sliceProgessPanel(wx.Panel): profile.putProfileSetting('skirt_line_count', '0') profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') + float(profile.getPreference('extruder_offset_x%d' % (idx)))) profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') + float(profile.getPreference('extruder_offset_y%d' % (idx)))) + profile.putProfileSetting('alternative_center', self.filelist[0]) if len(self.filelist) > 1: profile.putProfileSetting('add_start_end_gcode', 'False') profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp') @@ -105,7 +106,7 @@ class sliceProgessPanel(wx.Panel): status += " Print time: %02d:%02d" % (int(result.gcode.totalMoveTimeMinute / 60), int(result.gcode.totalMoveTimeMinute % 60)) cost = result.gcode.calculateCost() if cost != False: - status += "Cost: %s" % (cost) + status += " Cost: %s" % (cost) self.statusText.SetLabel(status) if exporer.hasExporer(): self.openFileLocationButton = wx.Button(self, -1, "Open file location") diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 7e83d3f4..a84f1ec5 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -56,6 +56,7 @@ class gcode(): currentE = 0.0 totalExtrusion = 0.0 maxExtrusion = 0.0 + currentExtruder = 0 totalMoveTimeMinute = 0.0 scale = 1.0 posAbs = True @@ -90,6 +91,15 @@ class gcode(): if pathType != "CUSTOM": startCodeDone = True line = line[0:line.find(';')] + T = self.getCodeInt(line, 'T') + if T is not None: + if currentExtruder > 0: + posOffset.x += float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) + posOffset.y += float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) + currentExtruder = T + if currentExtruder > 0: + posOffset.x -= float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) + posOffset.y -= float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) G = self.getCodeInt(line, 'G') if G is not None: @@ -102,17 +112,17 @@ class gcode(): oldPos = pos.copy() if x is not None: if posAbs: - pos.x = x * scale + pos.x = x * scale + posOffset.x else: pos.x += x * scale if y is not None: if posAbs: - pos.y = y * scale + pos.y = y * scale + posOffset.y else: pos.y += y * scale if z is not None: if posAbs: - pos.z = z * scale + pos.z = z * scale + posOffset.z else: pos.z += z * scale #Check if we have a new layer. From 8f3984634997618d9f056ed32d6c07d159e08ee1 Mon Sep 17 00:00:00 2001 From: Daid Date: Sun, 29 Apr 2012 14:50:52 +0200 Subject: [PATCH 12/30] Corrected extruder offset direction --- Cura/gui/sliceProgessPanel.py | 4 ++-- Cura/util/gcodeInterpreter.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index bb83266b..e3e96d25 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -66,8 +66,8 @@ class sliceProgessPanel(wx.Panel): if idx > 0: profile.putProfileSetting('fan_enabled', 'False') profile.putProfileSetting('skirt_line_count', '0') - profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') + float(profile.getPreference('extruder_offset_x%d' % (idx)))) - profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') + float(profile.getPreference('extruder_offset_y%d' % (idx)))) + profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - float(profile.getPreference('extruder_offset_x%d' % (idx)))) + profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - float(profile.getPreference('extruder_offset_y%d' % (idx)))) profile.putProfileSetting('alternative_center', self.filelist[0]) if len(self.filelist) > 1: profile.putProfileSetting('add_start_end_gcode', 'False') diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index a84f1ec5..5b7bda16 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -93,13 +93,13 @@ class gcode(): line = line[0:line.find(';')] T = self.getCodeInt(line, 'T') if T is not None: - if currentExtruder > 0: - posOffset.x += float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) - posOffset.y += float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) - currentExtruder = T if currentExtruder > 0: posOffset.x -= float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) posOffset.y -= float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) + currentExtruder = T + if currentExtruder > 0: + posOffset.x += float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) + posOffset.y += float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) G = self.getCodeInt(line, 'G') if G is not None: From 11d90227419c3eb27bfac8e1c063b2f651457b61 Mon Sep 17 00:00:00 2001 From: daid Date: Tue, 1 May 2012 11:39:52 +0200 Subject: [PATCH 13/30] Update preferences to allow math expressions. Fixed #86 --- Cura/gui/preview3d.py | 2 +- Cura/gui/projectPlanner.py | 12 ++++++------ Cura/gui/sliceProgessPanel.py | 4 ++-- Cura/util/gcodeInterpreter.py | 14 +++++++------- Cura/util/profile.py | 9 ++++++++- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index f905d0f4..ec525096 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -47,7 +47,7 @@ class previewPanel(wx.Panel): self.objectsMinV = None self.objectsMaxV = None self.loadThread = None - self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height'))) + self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')) self.machineCenter = util3d.Vector3(float(profile.getProfileSetting('machine_center_x')), float(profile.getProfileSetting('machine_center_y')), 0) self.toolbar = toolbarUtil.Toolbar(self) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 448b31b2..9b664ce5 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -39,15 +39,15 @@ class projectPlanner(wx.Frame): self.list = [] self.selection = None - self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height'))) - self.headSizeMin = util3d.Vector3(float(profile.getPreference('extruder_head_size_min_x')), float(profile.getPreference('extruder_head_size_min_y')),0) - self.headSizeMax = util3d.Vector3(float(profile.getPreference('extruder_head_size_max_x')), float(profile.getPreference('extruder_head_size_max_y')),0) + self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')) + self.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0) + self.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0) self.extruderOffset = [ util3d.Vector3(0,0,0), - util3d.Vector3(float(profile.getPreference('extruder_offset_x1')), float(profile.getPreference('extruder_offset_y1')), 0), - util3d.Vector3(float(profile.getPreference('extruder_offset_x2')), float(profile.getPreference('extruder_offset_y2')), 0), - util3d.Vector3(float(profile.getPreference('extruder_offset_x3')), float(profile.getPreference('extruder_offset_y3')), 0)] + util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0), + util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0), + util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0)] self.toolbar = toolbarUtil.Toolbar(self) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index e3e96d25..17fc7857 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -66,8 +66,8 @@ class sliceProgessPanel(wx.Panel): if idx > 0: profile.putProfileSetting('fan_enabled', 'False') profile.putProfileSetting('skirt_line_count', '0') - profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - float(profile.getPreference('extruder_offset_x%d' % (idx)))) - profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - float(profile.getPreference('extruder_offset_y%d' % (idx)))) + profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx))) + profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx))) profile.putProfileSetting('alternative_center', self.filelist[0]) if len(self.filelist) > 1: profile.putProfileSetting('add_start_end_gcode', 'False') diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 5b7bda16..3af69bb4 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -36,11 +36,11 @@ class gcode(): #Calculates the weight of the filament in kg radius = float(profile.getProfileSetting('filament_diameter')) / 2 volumeM3 = (self.extrusionAmount * (math.pi * radius * radius)) / (1000*1000*1000) - return volumeM3 * float(profile.getPreference('filament_density')) + return volumeM3 * profile.getPreferenceFloat('filament_density') def calculateCost(self): - cost_kg = float(profile.getPreference('filament_cost_kg')) - cost_meter = float(profile.getPreference('filament_cost_meter')) + cost_kg = profile.getPreferenceFloat('filament_cost_kg') + cost_meter = profile.getPreferenceFloat('filament_cost_meter') if cost_kg > 0.0 and cost_meter > 0.0: return "%.2f / %.2f" % (self.calculateWeight() * cost_kg, self.extrusionAmount / 1000 * cost_meter) elif cost_kg > 0.0: @@ -94,12 +94,12 @@ class gcode(): T = self.getCodeInt(line, 'T') if T is not None: if currentExtruder > 0: - posOffset.x -= float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) - posOffset.y -= float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) + posOffset.x -= profile.getPreferenceFloat('extruder_offset_x%d' % (currentExtruder)) + posOffset.y -= profile.getPreferenceFloat('extruder_offset_y%d' % (currentExtruder)) currentExtruder = T if currentExtruder > 0: - posOffset.x += float(profile.getPreference('extruder_offset_x%d' % (currentExtruder))) - posOffset.y += float(profile.getPreference('extruder_offset_y%d' % (currentExtruder))) + posOffset.x += profile.getPreferenceFloat('extruder_offset_x%d' % (currentExtruder)) + posOffset.y += profile.getPreferenceFloat('extruder_offset_y%d' % (currentExtruder)) G = self.getCodeInt(line, 'G') if G is not None: diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 046617cb..96e1eb35 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -236,6 +236,13 @@ globalPreferenceParser = None def getPreferencePath(): return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../preferences.ini")) +def getPreferenceFloat(name): + try: + return float(eval(getPreference(name), {}, {})) + + except (ValueError, SyntaxError): + return 0.0 + def getPreference(name): global globalPreferenceParser if globalPreferenceParser == None: @@ -346,7 +353,7 @@ def getAlterationFileContents(filename): if filename == 'start.gcode': #For the start code, hack the temperature and the steps per E value into it. So the temperature is reached before the start code extrusion. #We also set our steps per E here, if configured. - eSteps = float(getPreference('steps_per_e')) + eSteps = getPreferenceFloat('steps_per_e') if eSteps > 0: prefix += 'M92 E%f\n' % (eSteps) temp = getProfileSettingFloat('print_temperature') From 25c753fffa3f3da64444e74e26c46f7b8d135326 Mon Sep 17 00:00:00 2001 From: daid Date: Tue, 1 May 2012 11:45:34 +0200 Subject: [PATCH 14/30] Fixed crash on minimal layer time of zero. Fixed #84 --- .../skeinforge_plugins/craft_plugins/cool.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py index 5a4f5491..f018e0c6 100644 --- a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py +++ b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py @@ -223,6 +223,8 @@ class CoolSkein: def addCoolTemperature(self, remainingOrbitTime): 'Parse a gcode line and add it to the cool skein.' + if self.repository.minimumLayerTime.value < 0.0001: + return layerCool = self.repository.maximumCool.value * remainingOrbitTime / self.repository.minimumLayerTime.value if self.isBridgeLayer: layerCool = max(self.repository.bridgeCool.value, layerCool) From 3d70d671453f2d75f7f0155d9df08bd88d4e4a34 Mon Sep 17 00:00:00 2001 From: Daid Date: Tue, 1 May 2012 18:40:10 +0200 Subject: [PATCH 15/30] Save last known Z position in multi color slicing. --- Cura/gui/sliceProgessPanel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index e3e96d25..7f10300e 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -1,7 +1,7 @@ from __future__ import absolute_import import __init__ -import wx, sys, os, math, threading, subprocess, time +import wx, sys, os, math, threading, subprocess, time, re from util import profile from util import sliceRun @@ -202,6 +202,8 @@ class WorkerThread(threading.Thread): hasLine = True if line.startswith(';LAYER:'): break + if 'Z' in line: + lastZ = float(re.search('Z([^\s]+)', line).group(1)) if not layerHasLine: nextExtruder = files.index(f) resultFile.write(';LAYER:%d\n' % (layerNr)) From 92c42d1afa7f8a7c2aa05b6a1b62fa7f1c554faf Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 2 May 2012 14:14:41 +0200 Subject: [PATCH 16/30] Only show gcode buttons when GCode is loaded. Only show layer selection in GCode and mixed view. Fixed #87 --- Cura/gui/preview3d.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index ec525096..ee1ed79e 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -63,7 +63,6 @@ class previewPanel(wx.Panel): self.xrayViewButton = toolbarUtil.RadioButton(self.toolbar, group, 'view-xray-on.png', 'view-xray-off.png', 'X-Ray view', callback=self.OnViewChange) self.gcodeViewButton = toolbarUtil.RadioButton(self.toolbar, group, 'view-gcode-on.png', 'view-gcode-off.png', 'GCode view', callback=self.OnViewChange) self.mixedViewButton = toolbarUtil.RadioButton(self.toolbar, group, 'view-mixed-on.png', 'view-mixed-off.png', 'Mixed model/GCode view', callback=self.OnViewChange) - self.OnViewChange() self.toolbar.AddSeparator() self.layerSpin = wx.SpinCtrl(self.toolbar, -1, '', size=(21*4,21), style=wx.SP_ARROW_KEYS) @@ -107,7 +106,7 @@ class previewPanel(wx.Panel): self.toolbar2.AddControl(self.rotate) self.toolbar2.Realize() - self.updateToolbar() + self.OnViewChange() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.toolbar, 0, flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, border=1) @@ -272,7 +271,9 @@ class previewPanel(wx.Panel): pass def updateToolbar(self): - self.layerSpin.Show(self.gcode != None) + self.gcodeViewButton.Show(self.gcode != None) + self.mixedViewButton.Show(self.gcode != None) + self.layerSpin.Show(self.glCanvas.viewMode == "GCode" or self.glCanvas.viewMode == "Mixed") if self.gcode != None: self.layerSpin.SetRange(1, len(self.gcode.layerList)) self.toolbar.Realize() @@ -288,6 +289,7 @@ class previewPanel(wx.Panel): self.glCanvas.viewMode = "GCode" elif self.mixedViewButton.GetValue(): self.glCanvas.viewMode = "Mixed" + self.updateToolbar() self.glCanvas.Refresh() def updateModelTransform(self, f=0): From 5e8a0c92c088711b1e84a503f838d185f8c5518c Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 2 May 2012 14:21:21 +0200 Subject: [PATCH 17/30] Add loaded filename into title bar. --- Cura/gui/mainWindow.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 3cd22ab2..34d2f965 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -86,6 +86,7 @@ class mainWindow(configBase.configWindowBase): if profile.getPreference('lastFile') != '': self.filelist = profile.getPreference('lastFile').split(';') + self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion()) else: self.filelist = [] self.progressPanelList = [] @@ -299,6 +300,7 @@ class mainWindow(configBase.configWindowBase): filelist.append(self._showOpenDialog("Open file to print")) if filelist[-1] == False: return + self.SetTitle(filelist[-1] + ' - Cura - ' + version.getVersion()) self.filelist = filelist profile.putPreference('lastFile', ';'.join(self.filelist)) self.preview3d.loadModelFiles(self.filelist) From a5237fea44184511903c4d88b7ee0621b62e1d1e Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 2 May 2012 17:15:55 +0200 Subject: [PATCH 18/30] Very basic syntax highlight for comments in the GCode editor for start/end code. --- Cura/gui/alterationPanel.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/Cura/gui/alterationPanel.py b/Cura/gui/alterationPanel.py index c102f19b..2fa320c4 100644 --- a/Cura/gui/alterationPanel.py +++ b/Cura/gui/alterationPanel.py @@ -1,4 +1,4 @@ -import wx +import wx, wx.stc import sys,math,threading,os from util import profile @@ -10,12 +10,21 @@ class alterationPanel(wx.Panel): self.alterationFileList = ['start.gcode', 'end.gcode', 'support_start.gcode', 'support_end.gcode', 'nextobject.gcode', 'replace.csv'] self.currentFile = None - self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB) - self.textArea.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + #self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB) + #self.textArea.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) + self.textArea = wx.stc.StyledTextCtrl(self) + self.textArea.SetLexer(wx.stc.STC_LEX_CONTAINER) self.list = wx.ListBox(self, choices=self.alterationFileList, style=wx.LB_SINGLE) self.list.SetSelection(0) self.Bind(wx.EVT_LISTBOX, self.OnSelect, self.list) self.textArea.Bind(wx.EVT_KILL_FOCUS, self.OnFocusLost, self.textArea) + self.textArea.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle) + + fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() + fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() + self.textArea.SetStyleBits(5) + self.textArea.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%s,size:%d" % (fontName, fontSize)) + self.textArea.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize)) sizer = wx.GridBagSizer() sizer.Add(self.list, (0,0), span=(1,1), flag=wx.EXPAND) @@ -32,9 +41,24 @@ class alterationPanel(wx.Panel): self.currentFile = self.list.GetSelection() def loadFile(self, filename): - self.textArea.SetValue(profile.getAlterationFile(filename)) + #self.textArea.SetValue(profile.getAlterationFile(filename)) + self.textArea.SetText(profile.getAlterationFile(filename)) def OnFocusLost(self, e): if self.currentFile == self.list.GetSelection(): - profile.setAlterationFile(self.alterationFileList[self.list.GetSelection()], self.textArea.GetValue()) + #profile.setAlterationFile(self.alterationFileList[self.list.GetSelection()], self.textArea.GetValue()) + profile.setAlterationFile(self.alterationFileList[self.list.GetSelection()], self.textArea.GetText()) + + def OnStyle(self, e): + #for lineNr in xrange(0, + lineNr = self.textArea.LineFromPosition(self.textArea.GetEndStyled()) + while self.textArea.PositionFromLine(lineNr) > -1: + line = self.textArea.GetLine(lineNr) + self.textArea.StartStyling(self.textArea.PositionFromLine(lineNr), 31) + self.textArea.SetStyling(self.textArea.LineLength(lineNr), wx.stc.STC_STYLE_DEFAULT) + if ';' in line: + pos = line.index(';') + self.textArea.StartStyling(self.textArea.PositionFromLine(lineNr) + pos, 31) + self.textArea.SetStyling(self.textArea.LineLength(lineNr) - pos, 1) + lineNr += 1 From 9385aa8c2513d5891ad47a72e94ccb0ac794b592 Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 2 May 2012 17:54:29 +0200 Subject: [PATCH 19/30] Move gcode formated text to own file. --- Cura/gui/alterationPanel.py | 32 +++++--------------------------- Cura/gui/gcodeTextArea.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 Cura/gui/gcodeTextArea.py diff --git a/Cura/gui/alterationPanel.py b/Cura/gui/alterationPanel.py index 2fa320c4..5f5098d6 100644 --- a/Cura/gui/alterationPanel.py +++ b/Cura/gui/alterationPanel.py @@ -1,6 +1,7 @@ -import wx, wx.stc +import wx import sys,math,threading,os +from gui import gcodeTextArea from util import profile class alterationPanel(wx.Panel): @@ -12,19 +13,11 @@ class alterationPanel(wx.Panel): #self.textArea = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_PROCESS_TAB) #self.textArea.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) - self.textArea = wx.stc.StyledTextCtrl(self) - self.textArea.SetLexer(wx.stc.STC_LEX_CONTAINER) + self.textArea = gcodeTextArea.GcodeTextArea(self) self.list = wx.ListBox(self, choices=self.alterationFileList, style=wx.LB_SINGLE) self.list.SetSelection(0) self.Bind(wx.EVT_LISTBOX, self.OnSelect, self.list) self.textArea.Bind(wx.EVT_KILL_FOCUS, self.OnFocusLost, self.textArea) - self.textArea.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle) - - fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() - fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() - self.textArea.SetStyleBits(5) - self.textArea.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%s,size:%d" % (fontName, fontSize)) - self.textArea.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize)) sizer = wx.GridBagSizer() sizer.Add(self.list, (0,0), span=(1,1), flag=wx.EXPAND) @@ -41,24 +34,9 @@ class alterationPanel(wx.Panel): self.currentFile = self.list.GetSelection() def loadFile(self, filename): - #self.textArea.SetValue(profile.getAlterationFile(filename)) - self.textArea.SetText(profile.getAlterationFile(filename)) + self.textArea.SetValue(profile.getAlterationFile(filename)) def OnFocusLost(self, e): if self.currentFile == self.list.GetSelection(): - #profile.setAlterationFile(self.alterationFileList[self.list.GetSelection()], self.textArea.GetValue()) - profile.setAlterationFile(self.alterationFileList[self.list.GetSelection()], self.textArea.GetText()) - - def OnStyle(self, e): - #for lineNr in xrange(0, - lineNr = self.textArea.LineFromPosition(self.textArea.GetEndStyled()) - while self.textArea.PositionFromLine(lineNr) > -1: - line = self.textArea.GetLine(lineNr) - self.textArea.StartStyling(self.textArea.PositionFromLine(lineNr), 31) - self.textArea.SetStyling(self.textArea.LineLength(lineNr), wx.stc.STC_STYLE_DEFAULT) - if ';' in line: - pos = line.index(';') - self.textArea.StartStyling(self.textArea.PositionFromLine(lineNr) + pos, 31) - self.textArea.SetStyling(self.textArea.LineLength(lineNr) - pos, 1) - lineNr += 1 + profile.setAlterationFile(self.alterationFileList[self.list.GetSelection()], self.textArea.GetValue()) diff --git a/Cura/gui/gcodeTextArea.py b/Cura/gui/gcodeTextArea.py new file mode 100644 index 00000000..e6d85655 --- /dev/null +++ b/Cura/gui/gcodeTextArea.py @@ -0,0 +1,36 @@ +import wx, wx.stc +import sys,math,os + +from util import profile + +class GcodeTextArea(wx.stc.StyledTextCtrl): + def __init__(self, parent): + super(GcodeTextArea, self).__init__(parent) + + self.SetLexer(wx.stc.STC_LEX_CONTAINER) + self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyle) + + fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() + fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() + self.SetStyleBits(5) + self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%s,size:%d" % (fontName, fontSize)) + self.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize)) + + def OnStyle(self, e): + lineNr = self.LineFromPosition(self.GetEndStyled()) + while self.PositionFromLine(lineNr) > -1: + line = self.GetLine(lineNr) + self.StartStyling(self.PositionFromLine(lineNr), 31) + self.SetStyling(self.LineLength(lineNr), wx.stc.STC_STYLE_DEFAULT) + if ';' in line: + pos = line.index(';') + self.StartStyling(self.PositionFromLine(lineNr) + pos, 31) + self.SetStyling(self.LineLength(lineNr) - pos, 1) + lineNr += 1 + + def GetValue(self): + return self.GetText() + + def SetValue(self, s): + self.SetText(s) + From e29261a992d85b599af3f21357d93d6504903079 Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 3 May 2012 12:29:55 +0200 Subject: [PATCH 20/30] Added more GCode validation to GCode editor. Made temp changes to profile really temp so they are never stored in the ini file. Fixed crash bug in skeinforge where there is no layer code. --- .../skeinforge_plugins/craft_plugins/cool.py | 7 +- Cura/gui/gcodeTextArea.py | 77 +++++++++++++++++-- Cura/gui/projectPlanner.py | 14 ++-- Cura/gui/sliceProgessPanel.py | 22 +++--- Cura/util/profile.py | 49 +++++++++++- 5 files changed, 138 insertions(+), 31 deletions(-) diff --git a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py index f018e0c6..eb363a8c 100644 --- a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py +++ b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py @@ -406,9 +406,10 @@ class CoolSkein: def setMultiplier(self, remainingOrbitTime): 'Set the feed and flow rate multiplier.' layerTimeActive = self.getLayerTimeActive() - self.multiplier = min(1.0, layerTimeActive / (remainingOrbitTime + layerTimeActive)) - - + if remainingOrbitTime + layerTimeActive > 0.00001: + self.multiplier = min(1.0, layerTimeActive / (remainingOrbitTime + layerTimeActive)) + else: + self.multiplier = 1.0 def main(): 'Display the cool dialog.' diff --git a/Cura/gui/gcodeTextArea.py b/Cura/gui/gcodeTextArea.py index e6d85655..6cb108a1 100644 --- a/Cura/gui/gcodeTextArea.py +++ b/Cura/gui/gcodeTextArea.py @@ -13,21 +13,86 @@ class GcodeTextArea(wx.stc.StyledTextCtrl): fontSize = wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() self.SetStyleBits(5) - self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%s,size:%d" % (fontName, fontSize)) - self.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize)) + self.StyleSetSpec(0, "face:%s,size:%d" % (fontName, fontSize)) + self.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize)) + self.IndicatorSetStyle(0, wx.stc.STC_INDIC_TT) + self.IndicatorSetForeground(0, "#0000FF") + self.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE) + self.IndicatorSetForeground(1, "#FF0000") + + #GCodes and MCodes as supported by Marlin + #GCode 21 is not really supported by Marlin, but we still do not report it as error as it's often used. + self.supportedGCodes = [0,1,2,3,4,21,28,90,91,92] + self.supportedMCodes = [17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,42,80,81,82,83,84,85,92,104,105,106,107,109,114,115,117,119,140,190,201,202,203,204,205,206,220,221,240,301,302,303,400,500,501,502,503,999] def OnStyle(self, e): lineNr = self.LineFromPosition(self.GetEndStyled()) while self.PositionFromLine(lineNr) > -1: line = self.GetLine(lineNr) - self.StartStyling(self.PositionFromLine(lineNr), 31) - self.SetStyling(self.LineLength(lineNr), wx.stc.STC_STYLE_DEFAULT) + start = self.PositionFromLine(lineNr) + length = self.LineLength(lineNr) + self.StartStyling(start, 255) + self.SetStyling(length, 0) if ';' in line: pos = line.index(';') - self.StartStyling(self.PositionFromLine(lineNr) + pos, 31) - self.SetStyling(self.LineLength(lineNr) - pos, 1) + self.StartStyling(start + pos, 31) + self.SetStyling(length - pos, 1) + length = pos + + pos = 0 + while pos < length: + if line[pos] in " \t\n\r": + while pos < length and line[pos] in " \t\n\r": + pos += 1 + else: + end = pos + while end < length and not line[end] in " \t\n\r": + end += 1 + if self.checkGCodePart(line[pos:end], start + pos): + self.StartStyling(start + pos, 0x20) + self.SetStyling(end - pos, 0x20) + pos = end lineNr += 1 + def checkGCodePart(self, part, pos): + if len(part) < 2: + self.StartStyling(pos, 0x40) + self.SetStyling(1, 0x40) + return True + if not part[0] in "GMXYZFESTBPIDCJ": + self.StartStyling(pos, 0x40) + self.SetStyling(1, 0x40) + return True + if part[1] == '{': + if part[-1] != '}': + return True + tag = part[2:-1] + if not profile.isProfileSetting(tag) and not profile.isPreference(tag): + self.StartStyling(pos + 2, 0x40) + self.SetStyling(len(tag), 0x40) + return True + elif part[0] in "GM": + try: + code = int(part[1:]) + except (ValueError): + self.StartStyling(pos + 1, 0x40) + self.SetStyling(len(part) - 1, 0x40) + return True + if part[0] == 'G': + if not code in self.supportedGCodes: + return True + if part[0] == 'M': + if not code in self.supportedMCodes: + return True + else: + try: + float(part[1:]) + except (ValueError): + self.StartStyling(pos + 1, 0x40) + self.SetStyling(len(part) - 1, 0x40) + return True + return False + def GetValue(self): return self.GetText() diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 9b664ce5..a198a76d 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -285,9 +285,7 @@ class projectPlanner(wx.Frame): return (maxX - minX) + (maxY - minY) def OnSlice(self, e): - oldProfile = profile.getGlobalProfileString() - - put = profile.putProfileSetting + put = profile.setTempOverride put('model_multiply_x', '1') put('model_multiply_y', '1') @@ -319,7 +317,7 @@ class projectPlanner(wx.Frame): actionList.append(action) #Restore the old profile. - profile.loadGlobalProfileFromString(oldProfile) + profile.resetTempOverride() dlg=wx.FileDialog(self, "Save project gcode file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE) dlg.SetWildcard("GCode file (*.gcode)|*.gcode") @@ -670,6 +668,7 @@ class ProjectSliceProgressWindow(wx.Frame): self.sizer.Add(self.statusText, (0,0), flag=wx.ALIGN_CENTER) self.sizer.Add(self.progressGauge, (1, 0), flag=wx.EXPAND) self.sizer.Add(self.progressGauge2, (2, 0), flag=wx.EXPAND) + self.sizer.Add(self.abortButton, (3,0), flag=wx.ALIGN_CENTER) self.sizer.AddGrowableCol(0) self.sizer.AddGrowableRow(0) @@ -702,7 +701,7 @@ class ProjectSliceProgressWindow(wx.Frame): def OnRun(self): resultFile = open(self.resultFilename, "w") - put = profile.putProfileSetting + put = profile.setTempOverride for action in self.actionList: p = subprocess.Popen(action.sliceCmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) line = p.stdout.readline() @@ -727,7 +726,6 @@ class ProjectSliceProgressWindow(wx.Frame): line = p.stdout.readline() self.returnCode = p.wait() - oldProfile = profile.getGlobalProfileString() put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x) put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y) put('clear_z', action.clearZ) @@ -743,7 +741,7 @@ class ProjectSliceProgressWindow(wx.Frame): resultFile.write(';TYPE:CUSTOM\n') resultFile.write(profile.getAlterationFileContents('nextobject.gcode')) resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action)) - profile.loadGlobalProfileFromString(oldProfile) + profile.resetTempOverride() f = open(action.filename[: action.filename.rfind('.')] + "_export.project_tmp", "r") data = f.read(4096) @@ -762,7 +760,7 @@ class ProjectSliceProgressWindow(wx.Frame): resultFile.close() self.abort = True sliceTime = time.time() - self.sliceStartTime - wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %d:%d' % (sliceTime / 60, sliceTime % 60)) + wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %02d:%02d' % (sliceTime / 60, sliceTime % 60)) wx.CallAfter(self.abortButton.SetLabel, 'Close') def main(): diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 17fc7857..3fd0ad02 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -59,21 +59,20 @@ class sliceProgessPanel(wx.Panel): if profile.getPreference('save_profile') == 'True': profile.saveGlobalProfile(self.filelist[0][: self.filelist[0].rfind('.')] + "_profile.ini") cmdList = [] - oldProfile = profile.getGlobalProfileString() for filename in self.filelist: idx = self.filelist.index(filename) print filename, idx if idx > 0: - profile.putProfileSetting('fan_enabled', 'False') - profile.putProfileSetting('skirt_line_count', '0') - profile.putProfileSetting('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx))) - profile.putProfileSetting('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx))) - profile.putProfileSetting('alternative_center', self.filelist[0]) + profile.setTempOverride('fan_enabled', 'False') + profile.setTempOverride('skirt_line_count', '0') + profile.setTempOverride('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx))) + profile.setTempOverride('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx))) + profile.setTempOverride('alternative_center', self.filelist[0]) if len(self.filelist) > 1: - profile.putProfileSetting('add_start_end_gcode', 'False') - profile.putProfileSetting('gcode_extension', 'multi_extrude_tmp') + profile.setTempOverride('add_start_end_gcode', 'False') + profile.setTempOverride('gcode_extension', 'multi_extrude_tmp') cmdList.append(sliceRun.getSliceCommand(filename)) - profile.loadGlobalProfileFromString(oldProfile) + profile.resetTempOverride() self.thread = WorkerThread(self, filelist, cmdList) def OnAbort(self, e): @@ -188,7 +187,10 @@ class WorkerThread(threading.Thread): resultFile.write(';TYPE:CUSTOM\n') resultFile.write(profile.getAlterationFileContents('start.gcode')) for filename in self.filelist: - files.append(open(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp', "r")) + if os.path.isfile(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp'): + files.append(open(filename[:filename.rfind('.')]+'_export.multi_extrude_tmp', "r")) + else: + return currentExtruder = 0 resultFile.write('T%d\n' % (currentExtruder)) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 96e1eb35..686a8d8b 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -67,6 +67,9 @@ profileDefaultSettings = { 'add_start_end_gcode': 'True', 'gcode_extension': 'gcode', + 'alternative_center': '', + 'clear_z': '0.0', + 'extruder': '0', } alterationDefault = { ####################################################################################### @@ -153,6 +156,7 @@ preferencesDefaultSettings = { ## Profile and preferences functions ######################################################### +## Profile functions def getDefaultProfilePath(): return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../current_profile.ini")) @@ -188,17 +192,31 @@ def getGlobalProfileString(): p = [] alt = [] + tempDone = [] if globalProfileParser.has_section('profile'): for key in globalProfileParser.options('profile'): - p.append(key + "=" + globalProfileParser.get('profile', key)) + if key in tempOverride: + p.append(key + "=" + unicode(tempOverride[key])) + tempDone.append(key) + else: + p.append(key + "=" + globalProfileParser.get('profile', key)) if globalProfileParser.has_section('alterations'): for key in globalProfileParser.options('alterations'): - alt.append(key + "=" + globalProfileParser.get('alterations', key)) + if key in tempOverride: + p.append(key + "=" + tempOverride[key]) + tempDone.append(key) + else: + alt.append(key + "=" + globalProfileParser.get('alterations', key)) + for key in tempOverride: + if key not in tempDone: + p.append(key + "=" + unicode(tempOverride[key])) ret = '\b'.join(p) + '\f' + '\b'.join(alt) ret = base64.b64encode(zlib.compress(ret, 9)) return ret def getProfileSetting(name): + if name in tempOverride: + return unicode(tempOverride[name]) #Check if we have a configuration file loaded, else load the default. if not globals().has_key('globalProfileParser'): loadGlobalProfile(getDefaultProfilePath()) @@ -230,6 +248,12 @@ def putProfileSetting(name, value): globalProfileParser.add_section('profile') globalProfileParser.set('profile', name, str(value)) +def isProfileSetting(name): + if name in profileDefaultSettings: + return True + return False + +## Preferences functions global globalPreferenceParser globalPreferenceParser = None @@ -239,11 +263,12 @@ def getPreferencePath(): def getPreferenceFloat(name): try: return float(eval(getPreference(name), {}, {})) - except (ValueError, SyntaxError): return 0.0 def getPreference(name): + if name in tempOverride: + return unicode(tempOverride[name]) global globalPreferenceParser if globalPreferenceParser == None: globalPreferenceParser = ConfigParser.ConfigParser() @@ -273,6 +298,18 @@ def putPreference(name, value): globalPreferenceParser.set('preference', name, unicode(value).encode("utf-8")) globalPreferenceParser.write(open(getPreferencePath(), 'w')) +def isPreference(name): + if name in preferencesDefaultSettings: + return True + return False + +## Temp overrides for multi-extruder slicing and the project planner. +tempOverride = {} +def setTempOverride(name, value): + tempOverride[name] = value +def resetTempOverride(): + tempOverride = {} + ######################################################### ## Utility functions to calculate common profile values ######################################################### @@ -316,7 +353,11 @@ def replaceTagMatch(m): tag = m.group(0)[1:-1] if tag in ['print_speed', 'retraction_speed', 'travel_speed', 'max_z_speed', 'bottom_layer_speed', 'cool_min_feedrate']: return str(getProfileSettingFloat(tag) * 60) - return str(getProfileSettingFloat(tag)) + if isProfileSetting(tag): + return str(getProfileSettingFloat(tag)) + if isPreference(tag): + return str(getProfileSettingFloat(tag)) + return tag ### Get aleration raw contents. (Used internally in Cura) def getAlterationFile(filename): From 32d1ea11c2cea843ff3290c1b28060a63aef265e Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 3 May 2012 18:41:58 +0200 Subject: [PATCH 21/30] Changed GCode preview code to be faster on layer switching. --- Cura/gui/preview3d.py | 58 +++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index ee1ed79e..a2949c91 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -1,11 +1,6 @@ from __future__ import division -import sys -import math -import threading -import re -import time -import os +import sys, math, threading, re, time, os from wx import glcanvas import wx @@ -102,7 +97,7 @@ class previewPanel(wx.Panel): self.rotateReset = toolbarUtil.NormalButton(self.toolbar2, self.OnRotateReset, 'object-rotate.png', 'Reset model rotation') self.rotate = wx.SpinCtrl(self.toolbar2, -1, profile.getProfileSetting('model_rotate_base'), size=(21*3,21), style=wx.SP_WRAP|wx.SP_ARROW_KEYS) self.rotate.SetRange(0, 360) - self.Bind(wx.EVT_TEXT, self.OnRotate) + self.rotate.Bind(wx.EVT_TEXT, self.OnRotate) self.toolbar2.AddControl(self.rotate) self.toolbar2.Realize() @@ -179,7 +174,6 @@ class previewPanel(wx.Panel): self.glCanvas.Refresh() def OnLayerNrChange(self, e): - self.gcodeDirty = True self.glCanvas.Refresh() def updateCenterX(self): @@ -378,6 +372,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.offsetY = 0 self.view3D = True self.gcodeDisplayList = None + self.gcodeDisplayListCount = 0 self.objColor = [[1.0, 0.8, 0.6, 1.0], [0.2, 1.0, 0.1, 1.0], [1.0, 0.2, 0.1, 1.0], [0.1, 0.2, 1.0, 1.0]] def OnMouseMotion(self,e): @@ -441,33 +436,37 @@ class PreviewGLCanvas(glcanvas.GLCanvas): opengl.DrawMachine(machineSize) if self.parent.gcode != None: - if self.gcodeDisplayList == None: - self.gcodeDisplayList = glGenLists(1); if self.parent.gcodeDirty: + if self.gcodeDisplayListCount < len(self.parent.gcode.layerList) or self.gcodeDisplayList == None: + if self.gcodeDisplayList != None: + glDeleteLists(self.gcodeDisplayList, self.gcodeDisplayListCount) + self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); + self.gcodeDisplayListCount = len(self.parent.gcode.layerList) self.parent.gcodeDirty = False - glNewList(self.gcodeDisplayList, GL_COMPILE) prevLayerZ = 0.0 curLayerZ = 0.0 layerThickness = 0.0 - filamentRadius = float(profile.getProfileSetting('filament_diameter')) / 2 + filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 filamentArea = math.pi * filamentRadius * filamentRadius - lineWidth = float(profile.getProfileSetting('nozzle_size')) / 2 / 10 + lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10 curLayerNum = 0 for layer in self.parent.gcode.layerList: + glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) + glDisable(GL_CULL_FACE) curLayerZ = layer[0].list[1].z layerThickness = curLayerZ - prevLayerZ prevLayerZ = layer[-1].list[-1].z for path in layer: c = 1.0 - if curLayerNum != self.parent.layerSpin.GetValue(): - if curLayerNum < self.parent.layerSpin.GetValue(): - c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1 - if c < 0.4: - c = 0.4 - else: - break + #if curLayerNum != self.parent.layerSpin.GetValue(): + # if curLayerNum < self.parent.layerSpin.GetValue(): + # c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1 + # if c < 0.4: + # c = 0.4 + # else: + # break if path.type == 'move': glColor3f(0,0,c) if path.type == 'extrude': @@ -529,9 +528,24 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glVertex3f(v.x, v.y, v.z) glEnd() curLayerNum += 1 - glEndList() + glEnable(GL_CULL_FACE) + glEndList() if self.viewMode == "GCode" or self.viewMode == "Mixed": - glCallList(self.gcodeDisplayList) + glEnable(GL_COLOR_MATERIAL) + glEnable(GL_LIGHTING) + glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0]) + for i in xrange(0, self.parent.layerSpin.GetValue() + 1): + c = 1.0 + if i < self.parent.layerSpin.GetValue(): + c = 0.9 - (self.parent.layerSpin.GetValue() - i) * 0.1 + if c < 0.4: + c = (0.4 + c) / 2 + if c < 0.1: + c = 0.1 + glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c]) + glCallList(self.gcodeDisplayList + i) + glDisable(GL_COLOR_MATERIAL) + glDisable(GL_LIGHTING) glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) for obj in self.parent.objectList: From 82a3aafc374b1d836ebbdf1ef43adfae583991ca Mon Sep 17 00:00:00 2001 From: Daid Date: Thu, 3 May 2012 20:09:46 +0200 Subject: [PATCH 22/30] Some fixes to the preview window OpenGL code. Needed after last changes in GCode preview. However, also changes the view height depending on the selected layer now. --- Cura/gui/gcodeTextArea.py | 2 +- Cura/gui/opengl.py | 3 + Cura/gui/preview3d.py | 263 +++++++++++++++++++------------------- 3 files changed, 138 insertions(+), 130 deletions(-) diff --git a/Cura/gui/gcodeTextArea.py b/Cura/gui/gcodeTextArea.py index 6cb108a1..3c023325 100644 --- a/Cura/gui/gcodeTextArea.py +++ b/Cura/gui/gcodeTextArea.py @@ -14,7 +14,7 @@ class GcodeTextArea(wx.stc.StyledTextCtrl): fontName = wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL).GetFaceName() self.SetStyleBits(5) self.StyleSetSpec(0, "face:%s,size:%d" % (fontName, fontSize)) - self.StyleSetSpec(1, "fore:#008000,face:%s,size:%d" % (fontName, fontSize)) + self.StyleSetSpec(1, "fore:#006000,face:%s,size:%d" % (fontName, fontSize)) self.IndicatorSetStyle(0, wx.stc.STC_INDIC_TT) self.IndicatorSetForeground(0, "#0000FF") self.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE) diff --git a/Cura/gui/opengl.py b/Cura/gui/opengl.py index f7331aad..92ffcdea 100644 --- a/Cura/gui/opengl.py +++ b/Cura/gui/opengl.py @@ -17,7 +17,9 @@ def InitGL(window, view3D, zoom): glViewport(0,0, size.GetWidth(), size.GetHeight()) glLightfv(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0]) + glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0]) + glEnable(GL_NORMALIZE) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_DEPTH_TEST) @@ -198,6 +200,7 @@ def DrawBox(vMin, vMax): glEnd() def DrawSTL(mesh): + glEnable(GL_CULL_FACE) for face in mesh.faces: glBegin(GL_TRIANGLES) v1 = face.v[0] diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index a2949c91..84eb7266 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -38,6 +38,7 @@ class previewPanel(wx.Panel): self.glCanvas = PreviewGLCanvas(self) self.objectList = [] + self.errorList = [] self.gcode = None self.objectsMinV = None self.objectsMaxV = None @@ -230,7 +231,6 @@ class previewPanel(wx.Panel): mesh = stl.stlModel() mesh.load(obj.filename) obj.dirty = False - obj.errorList = [] obj.mesh = mesh self.updateModelTransform() wx.CallAfter(self.updateToolbar) @@ -269,7 +269,7 @@ class previewPanel(wx.Panel): self.mixedViewButton.Show(self.gcode != None) self.layerSpin.Show(self.glCanvas.viewMode == "GCode" or self.glCanvas.viewMode == "Mixed") if self.gcode != None: - self.layerSpin.SetRange(1, len(self.gcode.layerList)) + self.layerSpin.SetRange(1, len(self.gcode.layerList) - 1) self.toolbar.Realize() def OnViewChange(self): @@ -421,8 +421,12 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glTranslate(0,0,-self.zoom) glRotate(-self.pitch, 1,0,0) glRotate(self.yaw, 0,0,1) - if self.parent.objectsMaxV != None: - glTranslate(0,0,-self.parent.objectsMaxV.z * profile.getProfileSettingFloat('model_scale') / 2) + if self.viewMode == "GCode" or self.viewMode == "Mixed": + if self.parent.gcode != None: + glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z) + else: + if self.parent.objectsMaxV != None: + glTranslate(0,0,-self.parent.objectsMaxV.z * profile.getProfileSettingFloat('model_scale') / 2) else: glScale(1.0/self.zoom, 1.0/self.zoom, 1.0) glTranslate(self.offsetX, self.offsetY, 0.0) @@ -435,118 +439,121 @@ class PreviewGLCanvas(glcanvas.GLCanvas): machineSize = self.parent.machineSize opengl.DrawMachine(machineSize) - if self.parent.gcode != None: - if self.parent.gcodeDirty: - if self.gcodeDisplayListCount < len(self.parent.gcode.layerList) or self.gcodeDisplayList == None: - if self.gcodeDisplayList != None: - glDeleteLists(self.gcodeDisplayList, self.gcodeDisplayListCount) - self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); - self.gcodeDisplayListCount = len(self.parent.gcode.layerList) - self.parent.gcodeDirty = False - prevLayerZ = 0.0 - curLayerZ = 0.0 - - layerThickness = 0.0 - filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 - filamentArea = math.pi * filamentRadius * filamentRadius - lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10 - - curLayerNum = 0 - for layer in self.parent.gcode.layerList: - glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) - glDisable(GL_CULL_FACE) - curLayerZ = layer[0].list[1].z - layerThickness = curLayerZ - prevLayerZ - prevLayerZ = layer[-1].list[-1].z - for path in layer: - c = 1.0 - #if curLayerNum != self.parent.layerSpin.GetValue(): - # if curLayerNum < self.parent.layerSpin.GetValue(): - # c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1 - # if c < 0.4: - # c = 0.4 - # else: - # break - if path.type == 'move': - glColor3f(0,0,c) - if path.type == 'extrude': - if path.pathType == 'FILL': - glColor3f(c/2,c/2,0) - elif path.pathType == 'WALL-INNER': - glColor3f(0,c,0) - elif path.pathType == 'SUPPORT': - glColor3f(0,c,c) - elif path.pathType == 'SKIRT': - glColor3f(0,c/2,c/2) - else: - glColor3f(c,0,0) - if path.type == 'retract': - glColor3f(0,c,c) - if c > 0.4 and path.type == 'extrude': - for i in xrange(0, len(path.list)-1): - v0 = path.list[i] - v1 = path.list[i+1] - - # Calculate line width from ePerDistance (needs layer thickness and filament diameter) - dist = (v0 - v1).vsize() - if dist > 0 and layerThickness > 0: - extrusionMMperDist = (v1.e - v0.e) / dist - lineWidth = extrusionMMperDist * filamentArea / layerThickness / 2 - - normal = (v0 - v1).cross(util3d.Vector3(0,0,1)) - normal.normalize() - v2 = v0 + normal * lineWidth - v3 = v1 + normal * lineWidth - v0 = v0 - normal * lineWidth - v1 = v1 - normal * lineWidth - - glBegin(GL_QUADS) - if path.pathType == 'FILL': #Remove depth buffer fighting on infill/wall overlap - glVertex3f(v0.x, v0.y, v0.z - 0.02) - glVertex3f(v1.x, v1.y, v1.z - 0.02) - glVertex3f(v3.x, v3.y, v3.z - 0.02) - glVertex3f(v2.x, v2.y, v2.z - 0.02) - else: - glVertex3f(v0.x, v0.y, v0.z - 0.01) - glVertex3f(v1.x, v1.y, v1.z - 0.01) - glVertex3f(v3.x, v3.y, v3.z - 0.01) - glVertex3f(v2.x, v2.y, v2.z - 0.01) - glEnd() - - #for v in path['list']: - # glBegin(GL_TRIANGLE_FAN) - # glVertex3f(v.x, v.y, v.z - 0.001) - # for i in xrange(0, 16+1): - # if path['pathType'] == 'FILL': #Remove depth buffer fighting on infill/wall overlap - # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.02) - # else: - # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.01) - # glEnd() - else: - glBegin(GL_LINE_STRIP) - for v in path.list: - glVertex3f(v.x, v.y, v.z) - glEnd() - curLayerNum += 1 - glEnable(GL_CULL_FACE) - glEndList() - if self.viewMode == "GCode" or self.viewMode == "Mixed": - glEnable(GL_COLOR_MATERIAL) - glEnable(GL_LIGHTING) - glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0]) - for i in xrange(0, self.parent.layerSpin.GetValue() + 1): + if self.parent.gcode != None and self.parent.gcodeDirty: + if self.gcodeDisplayListCount < len(self.parent.gcode.layerList) or self.gcodeDisplayList == None: + if self.gcodeDisplayList != None: + glDeleteLists(self.gcodeDisplayList, self.gcodeDisplayListCount) + self.gcodeDisplayList = glGenLists(len(self.parent.gcode.layerList)); + self.gcodeDisplayListCount = len(self.parent.gcode.layerList) + self.parent.gcodeDirty = False + prevLayerZ = 0.0 + curLayerZ = 0.0 + + layerThickness = 0.0 + filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2 + filamentArea = math.pi * filamentRadius * filamentRadius + lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10 + + curLayerNum = 0 + for layer in self.parent.gcode.layerList: + glNewList(self.gcodeDisplayList + curLayerNum, GL_COMPILE) + glDisable(GL_CULL_FACE) + curLayerZ = layer[0].list[1].z + layerThickness = curLayerZ - prevLayerZ + prevLayerZ = layer[-1].list[-1].z + for path in layer: c = 1.0 - if i < self.parent.layerSpin.GetValue(): - c = 0.9 - (self.parent.layerSpin.GetValue() - i) * 0.1 - if c < 0.4: - c = (0.4 + c) / 2 - if c < 0.1: - c = 0.1 - glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c]) - glCallList(self.gcodeDisplayList + i) - glDisable(GL_COLOR_MATERIAL) - glDisable(GL_LIGHTING) + #if curLayerNum != self.parent.layerSpin.GetValue(): + # if curLayerNum < self.parent.layerSpin.GetValue(): + # c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1 + # if c < 0.4: + # c = 0.4 + # else: + # break + if path.type == 'move': + glColor3f(0,0,c) + if path.type == 'extrude': + if path.pathType == 'FILL': + glColor3f(c/2,c/2,0) + elif path.pathType == 'WALL-INNER': + glColor3f(0,c,0) + elif path.pathType == 'SUPPORT': + glColor3f(0,c,c) + elif path.pathType == 'SKIRT': + glColor3f(0,c/2,c/2) + else: + glColor3f(c,0,0) + if path.type == 'retract': + glColor3f(0,c,c) + if c > 0.4 and path.type == 'extrude': + for i in xrange(0, len(path.list)-1): + v0 = path.list[i] + v1 = path.list[i+1] + + # Calculate line width from ePerDistance (needs layer thickness and filament diameter) + dist = (v0 - v1).vsize() + if dist > 0 and layerThickness > 0: + extrusionMMperDist = (v1.e - v0.e) / dist + lineWidth = extrusionMMperDist * filamentArea / layerThickness / 2 + + normal = (v0 - v1).cross(util3d.Vector3(0,0,1)) + normal.normalize() + v2 = v0 + normal * lineWidth + v3 = v1 + normal * lineWidth + v0 = v0 - normal * lineWidth + v1 = v1 - normal * lineWidth + + glBegin(GL_QUADS) + if path.pathType == 'FILL': #Remove depth buffer fighting on infill/wall overlap + glVertex3f(v0.x, v0.y, v0.z - 0.02) + glVertex3f(v1.x, v1.y, v1.z - 0.02) + glVertex3f(v3.x, v3.y, v3.z - 0.02) + glVertex3f(v2.x, v2.y, v2.z - 0.02) + else: + glVertex3f(v0.x, v0.y, v0.z - 0.01) + glVertex3f(v1.x, v1.y, v1.z - 0.01) + glVertex3f(v3.x, v3.y, v3.z - 0.01) + glVertex3f(v2.x, v2.y, v2.z - 0.01) + glEnd() + + #for v in path['list']: + # glBegin(GL_TRIANGLE_FAN) + # glVertex3f(v.x, v.y, v.z - 0.001) + # for i in xrange(0, 16+1): + # if path['pathType'] == 'FILL': #Remove depth buffer fighting on infill/wall overlap + # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.02) + # else: + # glVertex3f(v.x + math.cos(math.pi*2/16*i) * lineWidth, v.y + math.sin(math.pi*2/16*i) * lineWidth, v.z - 0.01) + # glEnd() + else: + glBegin(GL_LINE_STRIP) + for v in path.list: + glVertex3f(v.x, v.y, v.z) + glEnd() + curLayerNum += 1 + glEnable(GL_CULL_FACE) + glEndList() + if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): + glEnable(GL_COLOR_MATERIAL) + glEnable(GL_LIGHTING) + for i in xrange(0, self.parent.layerSpin.GetValue() + 1): + c = 1.0 + if i < self.parent.layerSpin.GetValue(): + c = 0.9 - (self.parent.layerSpin.GetValue() - i) * 0.1 + if c < 0.4: + c = (0.4 + c) / 2 + if c < 0.1: + c = 0.1 + glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0]) + glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c]) + glCallList(self.gcodeDisplayList + i) + glDisable(GL_LIGHTING) + glDisable(GL_COLOR_MATERIAL) + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0]); + + glColor3f(1.0,1.0,1.0) glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) for obj in self.parent.objectList: if obj.mesh == None: @@ -559,17 +566,15 @@ class PreviewGLCanvas(glcanvas.GLCanvas): opengl.DrawSTL(obj.mesh) glEndList() - glEnable(GL_NORMALIZE) if self.viewMode == "Transparent" or self.viewMode == "Mixed": glLightfv(GL_LIGHT0, GL_DIFFUSE, map(lambda x: x / 2, self.objColor[self.parent.objectList.index(obj)])) glLightfv(GL_LIGHT0, GL_AMBIENT, map(lambda x: x / 10, self.objColor[self.parent.objectList.index(obj)])) #If we want transparent, then first render a solid black model to remove the printer size lines. if self.viewMode != "Mixed": glDisable(GL_BLEND) - glDisable(GL_LIGHTING) - glColor3f(0,0,0) + glColor3f(0.0,0.0,0.0) self.drawModel(obj) - glColor3f(1,1,1) + glColor3f(1.0,1.0,1.0) #After the black model is rendered, render the model again but now with lighting and no depth testing. glDisable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) @@ -624,17 +629,17 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glEnable(GL_LIGHTING) self.drawModel(obj) - if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray": - glDisable(GL_LIGHTING) - glDisable(GL_DEPTH_TEST) - glDisable(GL_BLEND) - glColor3f(1,0,0) - #glBegin(GL_LINES) - #for err in self.parent.errorList: - # glVertex3f(err[0].x, err[0].y, err[0].z) - # glVertex3f(err[1].x, err[1].y, err[1].z) - #glEnd() - glEnable(GL_DEPTH_TEST) + if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray": + glDisable(GL_LIGHTING) + glDisable(GL_DEPTH_TEST) + glDisable(GL_BLEND) + glColor3f(1,0,0) + glBegin(GL_LINES) + for err in self.parent.errorList: + glVertex3f(err[0].x, err[0].y, err[0].z) + glVertex3f(err[1].x, err[1].y, err[1].z) + glEnd() + glEnable(GL_DEPTH_TEST) glFlush() def drawModel(self, obj): From c1dc9f4354c435916aeb195820ce167d18f7f086 Mon Sep 17 00:00:00 2001 From: Daid Date: Thu, 3 May 2012 20:11:20 +0200 Subject: [PATCH 23/30] Some code cleanup --- Cura/gui/preview3d.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 84eb7266..52665936 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -462,30 +462,22 @@ class PreviewGLCanvas(glcanvas.GLCanvas): layerThickness = curLayerZ - prevLayerZ prevLayerZ = layer[-1].list[-1].z for path in layer: - c = 1.0 - #if curLayerNum != self.parent.layerSpin.GetValue(): - # if curLayerNum < self.parent.layerSpin.GetValue(): - # c = 0.9 - (self.parent.layerSpin.GetValue() - curLayerNum) * 0.1 - # if c < 0.4: - # c = 0.4 - # else: - # break if path.type == 'move': - glColor3f(0,0,c) + glColor3f(0,0,1) if path.type == 'extrude': if path.pathType == 'FILL': - glColor3f(c/2,c/2,0) + glColor3f(0.5,0.5,0) elif path.pathType == 'WALL-INNER': - glColor3f(0,c,0) + glColor3f(0,1,0) elif path.pathType == 'SUPPORT': - glColor3f(0,c,c) + glColor3f(0,1,1) elif path.pathType == 'SKIRT': - glColor3f(0,c/2,c/2) + glColor3f(0,0.5,0.5) else: - glColor3f(c,0,0) + glColor3f(1,0,0) if path.type == 'retract': - glColor3f(0,c,c) - if c > 0.4 and path.type == 'extrude': + glColor3f(0,1,1) + if path.type == 'extrude': for i in xrange(0, len(path.list)-1): v0 = path.list[i] v1 = path.list[i+1] From 79ef4ac2b6742d8600259bced3c38c7e9f202725 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 4 May 2012 11:47:55 +0200 Subject: [PATCH 24/30] There is no perfect solution for #90, but this makes it a bit better. --- Cura/gui/gcodeTextArea.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cura/gui/gcodeTextArea.py b/Cura/gui/gcodeTextArea.py index 3c023325..68d05249 100644 --- a/Cura/gui/gcodeTextArea.py +++ b/Cura/gui/gcodeTextArea.py @@ -19,6 +19,8 @@ class GcodeTextArea(wx.stc.StyledTextCtrl): self.IndicatorSetForeground(0, "#0000FF") self.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE) self.IndicatorSetForeground(1, "#FF0000") + self.SetWrapMode(wx.stc.STC_WRAP_NONE) + self.SetScrollWidth(1000) #GCodes and MCodes as supported by Marlin #GCode 21 is not really supported by Marlin, but we still do not report it as error as it's often used. From f437bc38eb143a86bb2d7a44d957da34d2188106 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 4 May 2012 12:03:08 +0200 Subject: [PATCH 25/30] Remove duplicate code. --- Cura/gui/projectPlanner.py | 26 ++------------------------ Cura/gui/sliceProgessPanel.py | 25 ++----------------------- Cura/util/sliceRun.py | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 47 deletions(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index a198a76d..97b9bbc8 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -636,28 +636,6 @@ class ProjectSliceProgressWindow(wx.Frame): self.startTime = time.time() self.sliceStartTime = time.time() - #How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left. - # TODO: Duplicate with sliceProgressPanel, move to sliceRun. - self.sliceStepTimeFactor = { - 'start': 3.3713991642, - 'slice': 15.4984838963, - 'preface': 5.17178297043, - 'inset': 116.362634182, - 'fill': 215.702672005, - 'multiply': 21.9536788464, - 'speed': 12.759510994, - 'raft': 31.4580039978, - 'skirt': 19.3436040878, - 'skin': 1.0, - 'joris': 1.0, - 'comb': 23.7805759907, - 'cool': 27.148763895, - 'dimension': 90.4914340973 - } - self.totalRunTimeFactor = 0 - for v in self.sliceStepTimeFactor.itervalues(): - self.totalRunTimeFactor += v - self.sizer = wx.GridBagSizer(2, 2) self.statusText = wx.StaticText(self, -1, "Building: %s" % (resultFilename)) self.progressGauge = wx.Gauge(self, -1) @@ -689,13 +667,13 @@ class ProjectSliceProgressWindow(wx.Frame): def SetProgress(self, stepName, layer, maxLayer): if self.prevStep != stepName: - self.totalDoneFactor += self.sliceStepTimeFactor[self.prevStep] + self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep] newTime = time.time() #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName self.startTime = newTime self.prevStep = stepName - progresValue = ((self.totalDoneFactor + self.sliceStepTimeFactor[stepName] * layer / maxLayer) / self.totalRunTimeFactor) * 10000 + progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000 self.progressGauge.SetValue(int(progresValue)) self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]") diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index 4eed4712..9e49e5b3 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -15,27 +15,6 @@ class sliceProgessPanel(wx.Panel): self.filelist = filelist self.abort = False - #How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left. - self.sliceStepTimeFactor = { - 'start': 3.3713991642, - 'slice': 15.4984838963, - 'preface': 5.17178297043, - 'inset': 116.362634182, - 'fill': 215.702672005, - 'multiply': 21.9536788464, - 'speed': 12.759510994, - 'raft': 31.4580039978, - 'skirt': 19.3436040878, - 'skin': 1.0, - 'joris': 1.0, - 'comb': 23.7805759907, - 'cool': 27.148763895, - 'dimension': 90.4914340973 - } - self.totalRunTimeFactor = 0 - for v in self.sliceStepTimeFactor.itervalues(): - self.totalRunTimeFactor += v - box = wx.StaticBox(self, -1, filelist[0]) self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) @@ -125,13 +104,13 @@ class sliceProgessPanel(wx.Panel): def SetProgress(self, stepName, layer, maxLayer): if self.prevStep != stepName: - self.totalDoneFactor += self.sliceStepTimeFactor[self.prevStep] + self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep] newTime = time.time() #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName self.startTime = newTime self.prevStep = stepName - progresValue = ((self.totalDoneFactor + self.sliceStepTimeFactor[stepName] * layer / maxLayer) / self.totalRunTimeFactor) * 10000 + progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000 self.progressGauge.SetValue(int(progresValue)) self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]") diff --git a/Cura/util/sliceRun.py b/Cura/util/sliceRun.py index edc304d3..4bc302a0 100644 --- a/Cura/util/sliceRun.py +++ b/Cura/util/sliceRun.py @@ -5,6 +5,28 @@ import platform, os, subprocess, sys from cura_sf.skeinforge_application.skeinforge_utilities import skeinforge_craft from util import profile +#How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left. +sliceStepTimeFactor = { + 'start': 3.3713991642, + 'slice': 15.4984838963, + 'preface': 5.17178297043, + 'inset': 116.362634182, + 'fill': 215.702672005, + 'multiply': 21.9536788464, + 'speed': 12.759510994, + 'raft': 31.4580039978, + 'skirt': 19.3436040878, + 'skin': 1.0, + 'joris': 1.0, + 'comb': 23.7805759907, + 'cool': 27.148763895, + 'dimension': 90.4914340973 +} + +totalRunTimeFactor = 0 +for v in sliceStepTimeFactor.itervalues(): + totalRunTimeFactor += v + def getPyPyExe(): "Return the path to the pypy executable if we can find it. Else return False" if platform.system() == "Windows": From dc54135db5534c8b84b428a500ab4ce57bc9fc75 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 4 May 2012 12:39:23 +0200 Subject: [PATCH 26/30] Fixed bug where tooltip was still shown when pressing open/save button on project planner. Added toolbar buttons for add/remove object in project planner. Added move up/down buttons to project planner. --- Cura/gui/projectPlanner.py | 40 ++++++++++++++++++++++++++++++++-- Cura/gui/toolbarUtil.py | 7 +++++- Cura/images/move-down.png | Bin 0 -> 623 bytes Cura/images/move-up.png | Bin 0 -> 672 bytes Cura/images/object-add.png | Bin 0 -> 926 bytes Cura/images/object-remove.png | Bin 0 -> 941 bytes 6 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 Cura/images/move-down.png create mode 100644 Cura/images/move-up.png create mode 100644 Cura/images/object-add.png create mode 100644 Cura/images/object-remove.png diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 97b9bbc8..2095042f 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -61,6 +61,13 @@ class projectPlanner(wx.Frame): toolbarUtil.NormalButton(self.toolbar, self.OnQuit, 'exit.png', 'Close project planner') self.toolbar.Realize() + + self.toolbar2 = toolbarUtil.Toolbar(self) + toolbarUtil.NormalButton(self.toolbar2, self.OnAddModel, 'object-add.png', 'Add model') + toolbarUtil.NormalButton(self.toolbar2, self.OnRemModel, 'object-remove.png', 'Remove model') + toolbarUtil.NormalButton(self.toolbar2, self.OnMoveUp, 'move-up.png', 'Move model up in print list') + toolbarUtil.NormalButton(self.toolbar2, self.OnMoveDown, 'move-down.png', 'Move model down in print list') + self.toolbar2.Realize() sizer = wx.GridBagSizer(2,2) self.SetSizer(sizer) @@ -71,7 +78,8 @@ class projectPlanner(wx.Frame): self.sliceButton = wx.Button(self, -1, "Slice") self.autoPlaceButton = wx.Button(self, -1, "Auto Place") - sizer.Add(self.toolbar, (0,0), span=(1,3), flag=wx.EXPAND) + sizer.Add(self.toolbar, (0,0), span=(1,1), flag=wx.EXPAND) + sizer.Add(self.toolbar2, (0,1), span=(1,2), flag=wx.EXPAND) sizer.Add(self.preview, (1,0), span=(4,1), flag=wx.EXPAND) sizer.Add(self.listbox, (1,1), span=(1,2), flag=wx.EXPAND) sizer.Add(self.addButton, (2,1), span=(1,1)) @@ -169,6 +177,7 @@ class projectPlanner(wx.Frame): item.swapYZ = cp.get(section, 'swapYZ') == 'True' if cp.has_option(section, 'extruder'): item.extuder = int(cp.get(section, 'extruder'))-1 + self.updateModelTransform(item) i += 1 self.list.append(item) @@ -231,9 +240,36 @@ class projectPlanner(wx.Frame): elif len(self.list) > 0: self.listbox.SetSelection(len(self.list) - 1) self.selection = None - self.OnListSelect(None) self.preview.Refresh() + def OnMoveUp(self, e): + if self.selection == None: + return + i = self.listbox.GetSelection() + if i == 0: + return + self.list.remove(self.selection) + self.list.insert(i-1, self.selection) + self._updateListbox() + self.preview.Refresh() + + def OnMoveDown(self, e): + if self.selection == None: + return + i = self.listbox.GetSelection() + if i == len(self.list) - 1: + return + self.list.remove(self.selection) + self.list.insert(i+1, self.selection) + self._updateListbox() + self.preview.Refresh() + + def _updateListbox(self): + self.listbox.Clear() + for item in self.list: + self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1]) + self.listbox.SetSelection(self.list.index(self.selection)) + def OnAutoPlace(self, e): bestAllowedSize = int(self.machineSize.y) bestArea = self._doAutoPlace(bestAllowedSize) diff --git a/Cura/gui/toolbarUtil.py b/Cura/gui/toolbarUtil.py index eba0a0b0..1ec088ef 100644 --- a/Cura/gui/toolbarUtil.py +++ b/Cura/gui/toolbarUtil.py @@ -180,6 +180,7 @@ class NormalButton(buttons.GenBitmapButton): super(NormalButton, self).__init__(parent, id, self.bitmap, size=size) self.helpText = helpText + self.callback = callback self.SetBezelWidth(1) self.SetUseFocusIndicator(False) @@ -187,10 +188,14 @@ class NormalButton(buttons.GenBitmapButton): self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) - self.Bind(wx.EVT_BUTTON, callback) + self.Bind(wx.EVT_BUTTON, self.OnButton) parent.AddControl(self) + def OnButton(self, event): + self.GetParent().OnPopupHide(event) + self.callback(event) + def OnMouseEnter(self, event): self.GetParent().OnPopupDisplay(event) event.Skip() diff --git a/Cura/images/move-down.png b/Cura/images/move-down.png new file mode 100644 index 0000000000000000000000000000000000000000..5891219e49603b6409d5479247ef1fa8a8cf71c2 GIT binary patch literal 623 zcmV-#0+9WQP)9KeakxIdTpje7cQjq<2c!^ z`Zm_SltDZPAt&#frRYyLt2KB&-G(%{q(iVQLTLEmE7;x%Q2E-zMx_cKcr*5=`6qt_ zJ8$Qx>E38HYSm`*8wpg%DHAF6Ak@qu=tdr9ZV&@0hK{|pLTM+EAS1zES!j~^>gMV) zSJgD~g*+^)fTA^sp+W%}T|?#b>p<{m+*@08kigJI_+;7}FTlfl=m%yDpG=!Ydu;Nd zxN@f?(x%l?jNxPW8<>{Ae&FyaVOl4ItmVe>FR)CpL^X>&_z8O)@9BsigdhL_002ov JPDHLkV1jC@76SkP literal 0 HcmV?d00001 diff --git a/Cura/images/move-up.png b/Cura/images/move-up.png new file mode 100644 index 0000000000000000000000000000000000000000..b3d9cef97e16ca46909765c0a67091c97908660b GIT binary patch literal 672 zcmV;R0$=@!P)0b000McNliru*9;vE5edJ)+6{olpPkPT$sbOg93kgUk5S3}N14Mj zJ9`2QPnU^Q!($^(CTVNfnvCJd_^zB_{%mUB`TqliV3)SpD2)!M;I1`LS5+JxL^j zO~OgoFbrKmJg8}SpP#!u{Y2f#ZY)Tn8ycjY)X_29v1zB_c}-ACQP&!9y++%+cK|hQ zcVTYU5iEd=eDJ6R!6Ub4fC}%BEHs50WXy+95J(Yr%Kip{H}1g9jtZOr0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iye& z3Kj{5dFFNi00SOLL_t(I%XO1WXk2v|#ea8Z?#$d|CYeqjd6+al+DHthjm4D)1u;@= zVrwl}5vo=wv7oq6M7nShDHIhcK3am-owzI|kopRQHjo4t%HWhtSMUHRYaUfy} zN!AyB$g1dBHS)>BFOA&1BVcBz*H+b6ROH=oQ}>R#wnKQtkd0r(4tQCe{gGRLO)RR& zM=J7F=c}WIe*v+f-fl!s1UBvNs%v|J;HI6RW!%&(3nTqBw?Brbs)bT6!OH9enZ)#% z8uQ_vV^=R&v7z2`h#c9n^F=Ed?Vy-Ru#uR?l(JNEaROF}`j!Wwn8F*{jwcu<9iL%k zc7l9r@mrr7dAarJ&#g)(Nj5%$l+y%q3G(SU>7`{JIs6&6Qw_NVG&hHpo?&xi2ena{ z9K3PJry@DUs`Up0grnOjB(6~vjSz`CIOL(Y2*wY^Whg9>kB^aE7$tb$LDWdjry?ML z<;SjV#SVliu8t$wRctR<`FZdt<@hBs>07u?1pEQC;-Vt>)CdZI0WE&Yw!yjc zORT3{p6_a;r$iLv?dkrd5 z^7b8Qc_O>EbiWhYiXCdYT`s3UE1+dYuZ+>xKgCazDXRCvdiifg2j=8+TmCPDdjzyv3XMXi2fudJk zgZsZT{d#&=yBc|4MGimk+oB`O2xb zZWVbCkv%GMy6ePzL(AKt*UCYM_{qfA!0Q120HrdU_LO0@pa1{>07*qoM6N<$f`@9d ADF6Tf literal 0 HcmV?d00001 diff --git a/Cura/images/object-remove.png b/Cura/images/object-remove.png new file mode 100644 index 0000000000000000000000000000000000000000..064e523caa1f55d66615dd4f4237f49790697909 GIT binary patch literal 941 zcmV;e15*5nP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iye& z3KtQK4o_hK00S*aL_t(I%XO1)OwVlwjFIu$*nB5#yd z?<#hd7x_E-ZAwLZ)R7N2y*zOJjsa7B&8Dipq9TU_6%Ey8q1_aSLn=0c>2a}Oeb3En zqcbYy7yyD-#uVQQTum{HLm*hma{MxDg2faEefUU2W(J%>$jrg=Ea}(H0vLsuMH?|a0Wu3eBdG;0M{jZHlVe0@7irw?<3M8x-;L)v-eWO+eTY3fgI>nJ zY`B?EUsX*_s3tF|CVoD)Qp7B14VV4_M!qF3eB}>(nVUpT`vrlQ?~vj_7addTm!#ed@2-2Ymi}G5r;* z=9L6!j&MyW2amo*=&60IL?Re|KVldxj9lc?=`red_{ZJiIE_oQLv2^4e>fa`@agJ` zx<*`qhaqiYU~uimGLGYr85_f6nn)%?I+5Uy0!d5QmbuSc` zZ)xPC&M#->uCIzaMI7d$QE3bQ^LEq!!NndupnLnfD;K3A+CQIhmX1i?i{L P00000NkvXXu0mjfo5Z`6 literal 0 HcmV?d00001 From 8b24d77aea8845c88590311310400a767a2372a1 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 4 May 2012 17:57:24 +0200 Subject: [PATCH 27/30] Added copy button to project planner, and cleaned up project planner code a bit. --- Cura/gui/projectPlanner.py | 229 +++++++++++++++++++--------------- Cura/gui/validators.py | 10 +- Cura/util/gcodeInterpreter.py | 4 +- Cura/util/stl.py | 4 +- Cura/util/util3d.py | 2 +- 5 files changed, 140 insertions(+), 109 deletions(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 2095042f..5d4bd80b 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -24,9 +24,108 @@ from util import util3d from util import stl from util import sliceRun -class Action(): +class Action(object): pass +class ProjectObject(stl.stlModel): + def __init__(self, filename): + super(ProjectObject, self).__init__() + + self.load(filename) + + self.filename = filename + self.scale = 1.0 + self.rotate = 0.0 + self.flipX = False + self.flipY = False + self.flipZ = False + self.swapXZ = False + self.swapYZ = False + self.extruder = 0 + + self.modelDisplayList = None + self.modelDirty = False + + self.origonalVertexes = list(self.vertexes) + for i in xrange(0, len(self.origonalVertexes)): + self.origonalVertexes[i] = self.origonalVertexes[i].copy() + self.getMinimumZ() + + self.centerX = -self.getMinimum().x + 5 + self.centerY = -self.getMinimum().y + 5 + + self.updateModelTransform() + + self.centerX = -self.getMinimum().x + 5 + self.centerY = -self.getMinimum().y + 5 + + def updateModelTransform(self): + rotate = self.rotate / 180.0 * math.pi + scaleX = 1.0 + scaleY = 1.0 + scaleZ = 1.0 + if self.flipX: + scaleX = -scaleX + if self.flipY: + scaleY = -scaleY + if self.flipZ: + scaleZ = -scaleZ + swapXZ = self.swapXZ + swapYZ = self.swapYZ + mat00 = math.cos(rotate) * scaleX + mat01 =-math.sin(rotate) * scaleY + mat10 = math.sin(rotate) * scaleX + mat11 = math.cos(rotate) * scaleY + + for i in xrange(0, len(self.origonalVertexes)): + x = self.origonalVertexes[i].x + y = self.origonalVertexes[i].y + z = self.origonalVertexes[i].z + if swapXZ: + x, z = z, x + if swapYZ: + y, z = z, y + self.vertexes[i].x = x * mat00 + y * mat01 + self.vertexes[i].y = x * mat10 + y * mat11 + self.vertexes[i].z = z * scaleZ + + for face in self.faces: + v1 = face.v[0] + v2 = face.v[1] + v3 = face.v[2] + face.normal = (v2 - v1).cross(v3 - v1) + face.normal.normalize() + + minZ = self.getMinimumZ() + minV = self.getMinimum() + maxV = self.getMaximum() + for v in self.vertexes: + v.z -= minZ + v.x -= minV.x + (maxV.x - minV.x) / 2 + v.y -= minV.y + (maxV.y - minV.y) / 2 + self.getMinimumZ() + self.modelDirty = True + + def clone(self): + p = ProjectObject(self.filename) + + p.centerX = self.centerX + 5 + p.centerY = self.centerY + 5 + + p.filename = self.filename + p.scale = self.scale + p.rotate = self.rotate + p.flipX = self.flipX + p.flipY = self.flipY + p.flipZ = self.flipZ + p.swapXZ = self.swapXZ + p.swapYZ = self.swapYZ + p.extruder = self.extruder + + p.updateModelTransform() + + return p + class projectPlanner(wx.Frame): "Main user interface window" def __init__(self): @@ -67,6 +166,7 @@ class projectPlanner(wx.Frame): toolbarUtil.NormalButton(self.toolbar2, self.OnRemModel, 'object-remove.png', 'Remove model') toolbarUtil.NormalButton(self.toolbar2, self.OnMoveUp, 'move-up.png', 'Move model up in print list') toolbarUtil.NormalButton(self.toolbar2, self.OnMoveDown, 'move-down.png', 'Move model down in print list') + toolbarUtil.NormalButton(self.toolbar2, self.OnCopy, 'copy.png', 'Make a copy of the current selected object') self.toolbar2.Realize() sizer = wx.GridBagSizer(2,2) @@ -163,9 +263,7 @@ class projectPlanner(wx.Frame): while cp.has_section('model_%d' % (i)): section = 'model_%d' % (i) - item = stl.stlModel() - item.filename = unicode(cp.get(section, 'filename'), "utf-8") - self.loadModelFile(item) + item = ProjectObject(unicode(cp.get(section, 'filename'), "utf-8")) item.centerX = float(cp.get(section, 'centerX')) item.centerY = float(cp.get(section, 'centerY')) item.scale = float(cp.get(section, 'scale')) @@ -177,7 +275,7 @@ class projectPlanner(wx.Frame): item.swapYZ = cp.get(section, 'swapYZ') == 'True' if cp.has_option(section, 'extruder'): item.extuder = int(cp.get(section, 'extruder'))-1 - self.updateModelTransform(item) + item.updateModelTransform() i += 1 self.list.append(item) @@ -185,6 +283,7 @@ class projectPlanner(wx.Frame): self.listbox.SetSelection(len(self.list)-1) self.OnListSelect(None) + self.preview.Refresh() dlg.Destroy() @@ -217,29 +316,19 @@ class projectPlanner(wx.Frame): dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") if dlg.ShowModal() == wx.ID_OK: for filename in dlg.GetPaths(): - item = stl.stlModel() - item.filename=filename + item = ProjectObject(filename) profile.putPreference('lastFile', item.filename) - if not(os.path.exists(item.filename)): - return - self.loadModelFile(item) self.list.append(item) - self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1]) - self.listbox.SetSelection(len(self.list)-1) - self.OnListSelect(None) + self.selection = item + self._updateListbox() + self.preview.Refresh() dlg.Destroy() def OnRemModel(self, e): if self.selection == None: return self.list.remove(self.selection) - i = self.listbox.GetSelection() - self.listbox.Delete(i) - if len(self.list) > i: - self.listbox.SetSelection(i) - elif len(self.list) > 0: - self.listbox.SetSelection(len(self.list) - 1) - self.selection = None + self._updateListbox() self.preview.Refresh() def OnMoveUp(self, e): @@ -264,11 +353,29 @@ class projectPlanner(wx.Frame): self._updateListbox() self.preview.Refresh() + def OnCopy(self, e): + if self.selection == None: + return + + item = self.selection.clone() + self.list.append(item) + self.selection = item + + self._updateListbox() + self.preview.Refresh() + def _updateListbox(self): self.listbox.Clear() for item in self.list: self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1]) - self.listbox.SetSelection(self.list.index(self.selection)) + if self.selection in self.list: + self.listbox.SetSelection(self.list.index(self.selection)) + elif len(self.list) > 0: + self.selection = self.list[0] + self.listbox.SetSelection(0) + else: + self.selection = None + self.listbox.SetSelection(-1) def OnAutoPlace(self, e): bestAllowedSize = int(self.machineSize.y) @@ -368,32 +475,6 @@ class projectPlanner(wx.Frame): pspw.Centre() pspw.Show(True) - def loadModelFile(self, item): - item.load(item.filename) - item.origonalVertexes = list(item.vertexes) - for i in xrange(0, len(item.origonalVertexes)): - item.origonalVertexes[i] = item.origonalVertexes[i].copy() - item.getMinimumZ() - - item.centerX = -item.getMinimum().x + 5 - item.centerY = -item.getMinimum().y + 5 - item.scale = 1.0 - item.rotate = 0.0 - item.flipX = False - item.flipY = False - item.flipZ = False - item.swapXZ = False - item.swapYZ = False - item.extruder = 0 - - item.modelDisplayList = None - item.modelDirty = False - - self.updateModelTransform(item) - - item.centerX = -item.getMinimum().x + 5 - item.centerY = -item.getMinimum().y + 5 - def OnScaleChange(self, e): if self.selection == None: return @@ -407,7 +488,8 @@ class projectPlanner(wx.Frame): if self.selection == None: return self.selection.rotate = float(self.rotateCtrl.GetValue()) - self.updateModelTransform(self.selection) + self.selection.updateModelTransform() + self.preview.Refresh() def OnExtruderChange(self, e): if self.selection == None: @@ -415,57 +497,6 @@ class projectPlanner(wx.Frame): self.selection.extruder = int(self.extruderCtrl.GetValue()) - 1 self.preview.Refresh() - def updateModelTransform(self, item): - rotate = item.rotate / 180.0 * math.pi - scaleX = 1.0 - scaleY = 1.0 - scaleZ = 1.0 - if item.flipX: - scaleX = -scaleX - if item.flipY: - scaleY = -scaleY - if item.flipZ: - scaleZ = -scaleZ - swapXZ = item.swapXZ - swapYZ = item.swapYZ - mat00 = math.cos(rotate) * scaleX - mat01 =-math.sin(rotate) * scaleY - mat10 = math.sin(rotate) * scaleX - mat11 = math.cos(rotate) * scaleY - - for i in xrange(0, len(item.origonalVertexes)): - x = item.origonalVertexes[i].x - y = item.origonalVertexes[i].y - z = item.origonalVertexes[i].z - if swapXZ: - x, z = z, x - if swapYZ: - y, z = z, y - item.vertexes[i].x = x * mat00 + y * mat01 - item.vertexes[i].y = x * mat10 + y * mat11 - item.vertexes[i].z = z * scaleZ - - for face in item.faces: - v1 = face.v[0] - v2 = face.v[1] - v3 = face.v[2] - face.normal = (v2 - v1).cross(v3 - v1) - face.normal.normalize() - - self.moveModel(item) - - def moveModel(self, item): - minZ = item.getMinimumZ() - min = item.getMinimum() - max = item.getMaximum() - for v in item.vertexes: - v.z -= minZ - v.x -= min.x + (max.x - min.x) / 2 - v.y -= min.y + (max.y - min.y) / 2 - item.getMinimumZ() - item.modelDirty = True - self.preview.Refresh() - class PreviewGLCanvas(glcanvas.GLCanvas): def __init__(self, parent): attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8) diff --git a/Cura/gui/validators.py b/Cura/gui/validators.py index b1da7783..f29e8d1e 100644 --- a/Cura/gui/validators.py +++ b/Cura/gui/validators.py @@ -11,7 +11,7 @@ SUCCESS = 0 WARNING = 1 ERROR = 2 -class validFloat(): +class validFloat(object): def __init__(self, setting, minValue = None, maxValue = None): self.setting = setting self.setting.validators.append(self) @@ -29,7 +29,7 @@ class validFloat(): except (ValueError, SyntaxError): return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid number or expression' -class validInt(): +class validInt(object): def __init__(self, setting, minValue = None, maxValue = None): self.setting = setting self.setting.validators.append(self) @@ -47,7 +47,7 @@ class validInt(): except (ValueError, SyntaxError): return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid whole number or expression' -class warningAbove(): +class warningAbove(object): def __init__(self, setting, minValueForWarning, warningMessage): self.setting = setting self.setting.validators.append(self) @@ -68,7 +68,7 @@ class warningAbove(): #We already have an error by the int/float validator in this case. return SUCCESS, '' -class wallThicknessValidator(): +class wallThicknessValidator(object): def __init__(self, setting): self.setting = setting self.setting.validators.append(self) @@ -94,7 +94,7 @@ class wallThicknessValidator(): #We already have an error by the int/float validator in this case. return SUCCESS, '' -class printSpeedValidator(): +class printSpeedValidator(object): def __init__(self, setting): self.setting = setting self.setting.validators.append(self) diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 3af69bb4..5714972c 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -9,13 +9,13 @@ import os from util import util3d from util import profile -class gcodePath(): +class gcodePath(object): def __init__(self, newType, pathType, startPoint): self.type = newType self.pathType = pathType self.list = [startPoint] -class gcode(): +class gcode(object): def __init__(self): self.regMatch = {} self.layerList = [] diff --git a/Cura/util/stl.py b/Cura/util/stl.py index 9b1323a2..bf7558b4 100644 --- a/Cura/util/stl.py +++ b/Cura/util/stl.py @@ -9,11 +9,11 @@ import struct from util import util3d -class stlFace(): +class stlFace(object): def __init__(self, v0, v1, v2): self.v = [v0, v1, v2] -class stlModel(): +class stlModel(object): def __init__(self): self.faces = [] self.vertexes = [] diff --git a/Cura/util/util3d.py b/Cura/util/util3d.py index 30b25159..d5411fc9 100644 --- a/Cura/util/util3d.py +++ b/Cura/util/util3d.py @@ -1,7 +1,7 @@ import math -class Vector3(): +class Vector3(object): def __init__(self, x=0.0, y=0.0, z=0.0): self.x = x self.y = y From 9a5508d0772fbcb3b18664c6796e920d6b6ead34 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 4 May 2012 18:10:39 +0200 Subject: [PATCH 28/30] Added the copy button image. (forgot that in my last commit) --- Cura/images/copy.png | Bin 0 -> 485 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Cura/images/copy.png diff --git a/Cura/images/copy.png b/Cura/images/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..5cdeb5fc73897c0b2b7fdb24a082a993cb2294c8 GIT binary patch literal 485 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=ff8>(m{G3O!W1aTUgGKN%6@}cL`d0sS5o>yped=IE{-7;x28@w z?{(Ng;8?o(vZal2UCV9SDn2q^kz14h;ArvQ8^O9iIQDs;w`*7+VDp{f_ZlWKjr z)#jWRvnDK(uc_Jn=1hKh7{h^v8aJ_m2#-3&dS~D8ALfP$ET*!d=Iaj$ESaLv%HXJJ zadX**`|pc8)DD~|l;Q1I%+aL4pv!&XZJDLtiIt|8wDsLQZsnLs95p=my!g*?kHg2f ze}skYh-*HqEXlpecGB}onN3VDlz0sp?)p^E4K+@`E$^}V!kg~`uY(tgCWzj2SkAUA zhv5~wSpvTuPll7r+MOC)9ESz0WW}p&`9(OEY-(cc;=5QH8+dok<}z*b-~0I2y#2;5 zm%ceYifxa*+WiUnz4IqbQQ=IBY~#^CEhHY#9paTJbKGK|^!~uRnp-kXG?@4ro-by5 zaqMZ<%Gv6Zf0wV?sdn1z0IR9imMNmDb$a0zwKG0V)~~O%Gci?|KU*m}BkiApw!tmN Y4DJ^lh1J@%z&K#=boFyt=akR{0F^SkGXMYp literal 0 HcmV?d00001 From c09861249e6fbad0aa8262f0d642316153cfae66 Mon Sep 17 00:00:00 2001 From: Daid Date: Fri, 4 May 2012 19:28:24 +0200 Subject: [PATCH 29/30] Added stat calculation after project slicing. --- Cura/gui/projectPlanner.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index a198a76d..5f77025e 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -23,6 +23,7 @@ from util import profile from util import util3d from util import stl from util import sliceRun +from util import gcodeInterpreter class Action(): pass @@ -722,6 +723,7 @@ class ProjectSliceProgressWindow(wx.Frame): if self.abort: p.terminate() wx.CallAfter(self.statusText.SetLabel, "Aborted by user.") + resultFile.close() return line = p.stdout.readline() self.returnCode = p.wait() @@ -758,9 +760,20 @@ class ProjectSliceProgressWindow(wx.Frame): resultFile.write(';TYPE:CUSTOM\n') resultFile.write(profile.getAlterationFileContents('end.gcode')) resultFile.close() + + gcode = gcodeInterpreter.gcode() + gcode.load(self.resultFilename) + self.abort = True sliceTime = time.time() - self.sliceStartTime - wx.CallAfter(self.statusText.SetLabel, 'Slicing took: %02d:%02d' % (sliceTime / 60, sliceTime % 60)) + status = "Slicing took: %02d:%02d\n" % (sliceTime / 60, sliceTime % 60) + status = "Filament: %.2fm %.2fg\n" % (gcode.extrusionAmount / 1000, gcode.calculateWeight() * 1000) + status += "Print time: %02d:%02d\n" % (int(gcode.totalMoveTimeMinute / 60), int(gcode.totalMoveTimeMinute % 60)) + cost = gcode.calculateCost() + if cost != False: + status += "Cost: %s\n" % (cost) + wx.CallAfter(self.statusText.SetLabel, status) + wx.CallAfter(self.abortButton.SetLabel, 'Close') def main(): From 424877fe0f729d2fc7dcbcada10946fa5fdde2cf Mon Sep 17 00:00:00 2001 From: Daid Date: Fri, 4 May 2012 19:58:00 +0200 Subject: [PATCH 30/30] Fix bug where tempOverrides where not cleared. --- Cura/util/profile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 686a8d8b..5e6f67ef 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -308,7 +308,7 @@ tempOverride = {} def setTempOverride(name, value): tempOverride[name] = value def resetTempOverride(): - tempOverride = {} + tempOverride.clear() ######################################################### ## Utility functions to calculate common profile values