From b7701af448f676f049fbccf80c5cc5597fb7a93f Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 4 Apr 2012 11:10:08 +0200 Subject: [PATCH 01/11] Use utf-8 to save preferences, so the last filename may contain unicode characters. --- Cura/util/profile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 5845e14cc3..213c57a519 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -158,7 +158,7 @@ def getPreference(name): globalPreferenceParser.set('preference', name, str(default)) print name + " not found in preferences, so using default: " + str(default) return default - return globalPreferenceParser.get('preference', name) + return unicode(globalPreferenceParser.get('preference', name), "utf-8") def putPreference(name, value): #Check if we have a configuration file loaded, else load the default. @@ -168,7 +168,7 @@ def putPreference(name, value): globalPreferenceParser.read(getPreferencePath()) if not globalPreferenceParser.has_section('preference'): globalPreferenceParser.add_section('preference') - globalPreferenceParser.set('preference', name, str(value)) + globalPreferenceParser.set('preference', name, str(value).encode("utf-8")) globalPreferenceParser.write(open(getPreferencePath(), 'w')) ######################################################### From 55c50df97281de98503d8add5ea01660e217088a Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 4 Apr 2012 11:16:26 +0200 Subject: [PATCH 02/11] Add printrun startmenu shortcut --- scripts/win32/installer.nsi | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/win32/installer.nsi b/scripts/win32/installer.nsi index c5d36f5b15..562bbaa9bb 100644 --- a/scripts/win32/installer.nsi +++ b/scripts/win32/installer.nsi @@ -85,6 +85,7 @@ Section "Cura Installer" CreateDirectory "$SMPROGRAMS\Cura ${VERSION}" CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura.lnk" "$INSTDIR\cura.bat" "" "$INSTDIR\cura.icon" 0 + CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\PrintRun.lnk" "$INSTDIR\printrun.bat" "" "$INSTDIR\cura.icon" 0 ; Set output path to the driver directory. SetOutPath "$INSTDIR\drivers\" @@ -108,9 +109,6 @@ Section "Uninstall" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" DeleteRegKey HKLM "SOFTWARE\Cura_${VERSION}" - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\Cura ${VERSION}\*.*" - ; Remove directories used RMDir /r "$SMPROGRAMS\Cura ${VERSION}" RMDir /r "$INSTDIR" From 374b2d1b5eae6bb9b5380b2cab7834e8fefbc0f6 Mon Sep 17 00:00:00 2001 From: daid Date: Wed, 4 Apr 2012 17:02:22 +0200 Subject: [PATCH 03/11] Add temperature control to print window --- Cura/gui/machineCom.py | 21 ++++++++++++++++++--- Cura/gui/printWindow.py | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Cura/gui/machineCom.py b/Cura/gui/machineCom.py index 7c1de22f02..5157fbe87d 100644 --- a/Cura/gui/machineCom.py +++ b/Cura/gui/machineCom.py @@ -106,18 +106,33 @@ class InstallFirmware(wx.Dialog): class VirtualPrinter(): def __init__(self): self.readList = ['start\n'] + self.temp = 0.0 + self.targetTemp = 0.0 def write(self, data): if self.readList == None: return print "Send: %s" % (data.rstrip()) - self.readList.append("ok\n") + if 'M104' in data: + try: + self.targetTemp = float(data[data.find('S')+1:]) + except: + pass + if 'M105' in data: + self.readList.append("ok T:%f/%f\n" % (self.temp, self.targetTemp)) + else: + self.readList.append("ok\n") def readline(self): if self.readList == None: return '' + n = 0 + self.temp = (self.temp + self.targetTemp) / 2 while len(self.readList) < 1: time.sleep(0.1) + n += 1 + if n == 20: + return '' if self.readList == None: return '' time.sleep(0.001) @@ -141,7 +156,7 @@ class MachineCom(): programmer.connect(port) programmer.close() print "Connecting to: %s %i" % (port, baudrate) - self.serial = Serial(port, baudrate, timeout=5) + self.serial = Serial(port, baudrate, timeout=2) break except ispBase.IspError: pass @@ -152,7 +167,7 @@ class MachineCom(): self.serial = VirtualPrinter() else: try: - self.serial = Serial(port, baudrate, timeout=5) + self.serial = Serial(port, baudrate, timeout=2) except: print "Unexpected error while connecting to serial port:" + port, sys.exc_info()[0] diff --git a/Cura/gui/printWindow.py b/Cura/gui/printWindow.py index ac42429015..b48650aded 100644 --- a/Cura/gui/printWindow.py +++ b/Cura/gui/printWindow.py @@ -1,7 +1,7 @@ from __future__ import absolute_import import __init__ -import wx, threading +import wx, threading, re from gui import machineCom from gui import icon @@ -27,7 +27,9 @@ class printWindow(wx.Frame): self.thread = None self.gcode = None self.gcodeList = None + self.sendList = [] self.printIdx = None + self.temp = None self.bufferLineCount = 4 self.sendCnt = 0 @@ -51,11 +53,20 @@ class printWindow(wx.Frame): self.printButton = wx.Button(self.panel, -1, 'Print GCode') self.cancelButton = wx.Button(self.panel, -1, 'Cancel print') self.progress = wx.Gauge(self.panel, -1) + + h = self.connectButton.GetSize().GetHeight() + self.temperatureSelect = wx.SpinCtrl(self.panel, -1, '0', size=(21*3,21), style=wx.SP_ARROW_KEYS) + self.temperatureSelect.SetRange(0, 400) + self.sizer.Add(self.connectButton, pos=(0,1)) #self.sizer.Add(self.loadButton, pos=(1,1)) self.sizer.Add(self.printButton, pos=(2,1)) self.sizer.Add(self.cancelButton, pos=(3,1)) self.sizer.Add(self.progress, pos=(4,0), span=(1,2), flag=wx.EXPAND) + + self.sizer.Add(wx.StaticText(self.panel, -1, "Temp:"), pos=(0,3)) + self.sizer.Add(self.temperatureSelect, pos=(0,4)) + self.sizer.AddGrowableRow(3) self.sizer.AddGrowableCol(0) @@ -65,6 +76,8 @@ class printWindow(wx.Frame): self.printButton.Bind(wx.EVT_BUTTON, self.OnPrint) self.cancelButton.Bind(wx.EVT_BUTTON, self.OnCancel) + self.Bind(wx.EVT_SPINCTRL, self.OnTempChange, self.temperatureSelect) + self.Layout() self.Fit() self.Centre() @@ -90,6 +103,8 @@ class printWindow(wx.Frame): else: self.progress.SetValue(self.printIdx) status += 'Line: %d/%d\n' % (self.printIdx, len(self.gcodeList)) + if self.temp != None: + status += 'Temp: %d\n' % (self.temp) self.statsText.SetLabel(status) def OnConnect(self, e): @@ -128,9 +143,13 @@ class printWindow(wx.Frame): self.thread.join() self.Destroy() + def OnTempChange(self, e): + self.sendCommand("M104 S%d" % (self.temperatureSelect.GetValue())) + def LoadGCodeFile(self, filename): if self.printIdx != None: return + #Send an initial M110 to reset the line counter to zero. gcodeList = ["M110"] for line in open(filename, 'r'): if ';' in line: @@ -146,6 +165,13 @@ class printWindow(wx.Frame): self.gcodeList = gcodeList self.UpdateButtonStates() self.UpdateProgress() + + def sendCommand(self, cmd): + if self.machineConnected: + if self.printIdx == None: + self.machineCom.sendCommand(cmd) + else: + self.sendList.append(cmd) def sendLine(self, lineNr): if lineNr >= len(self.gcodeList): @@ -155,7 +181,6 @@ class printWindow(wx.Frame): return True def PrinterMonitor(self): - skipCount = 0 while True: line = self.machineCom.readline() if line == None: @@ -170,10 +195,16 @@ class printWindow(wx.Frame): elif line.startswith("start"): self.machineConnected = True wx.CallAfter(self.UpdateButtonStates) - if self.printIdx != None: + if 'T:' in line: + self.temp = float(re.search("[0-9\.]*", line.split('T:')[1]).group(0)) + wx.CallAfter(self.UpdateProgress) + if self.printIdx == None: + if line == '': #When we have a communication "timeout" and we're not sending gcode read the temperature. + self.machineCom.sendCommand("M105") + else: if line.startswith("ok"): - if skipCount > 0: - skipCount -= 1 + if len(self.sendList) > 0: + self.machineCom.sendCommand(self.sendList.pop(0)) else: if self.sendLine(self.printIdx): self.printIdx += 1 From 835b7883caac609564e722e2613741ab5dc45502 Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 5 Apr 2012 16:50:59 +0200 Subject: [PATCH 04/11] Add bottom layer thickness. Fix bug with line with in 3D preview (was not calculated from layer thickness) --- Cura/cura_sf/fabmetheus_utilities/settings.py | 26 +++++++++++++++++-- .../skeinforge_plugins/craft_plugins/speed.py | 4 +++ Cura/gui/mainWindow.py | 4 +++ Cura/gui/preview3d.py | 5 +++- Cura/gui/printWindow.py | 2 +- Cura/gui/simpleMode.py | 3 +++ Cura/util/profile.py | 1 + Cura/util/sliceRun.py | 2 +- 8 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Cura/cura_sf/fabmetheus_utilities/settings.py b/Cura/cura_sf/fabmetheus_utilities/settings.py index aeb64c154c..61cc77f388 100644 --- a/Cura/cura_sf/fabmetheus_utilities/settings.py +++ b/Cura/cura_sf/fabmetheus_utilities/settings.py @@ -64,6 +64,27 @@ def calculateMultiplyDistance(setting): edgeWidth = calculateEdgeWidth(setting) return 10.0 / edgeWidth +def calcBottomLayerFlowRateRatio(setting): + bottomThickness = float(profile.getProfileSetting('bottom_thickness')) + layerThickness = float(profile.getProfileSetting('layer_height')) + if bottomThickness < layerThickness: + return 1.0 + return bottomThickness / layerThickness + +def calcExtraBottomThickness(setting): + bottomThickness = float(profile.getProfileSetting('bottom_thickness')) + layerThickness = float(profile.getProfileSetting('layer_height')) + if bottomThickness < layerThickness: + return 0.0 + return bottomThickness - layerThickness + +def calcLayerSkip(setting): + bottomThickness = float(profile.getProfileSetting('bottom_thickness')) + layerThickness = float(profile.getProfileSetting('layer_height')) + if bottomThickness < layerThickness: + return 0 + return int(math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1) + def getProfileInformation(): return { 'carve': { @@ -72,7 +93,7 @@ def getProfileInformation(): 'Extra_Decimal_Places_float': DEFSET, 'Import_Coarseness_ratio': DEFSET, 'Layer_Height_mm': storedSetting("layer_height"), - 'Layers_From_index': DEFSET, + 'Layers_From_index': calcLayerSkip, 'Layers_To_index': DEFSET, 'Correct_Mesh': DEFSET, 'Unproven_Mesh': DEFSET, @@ -90,7 +111,7 @@ def getProfileInformation(): },'bottom': { 'Activate_Bottom': DEFSET, 'Additional_Height_over_Layer_Thickness_ratio': DEFSET, - 'Altitude_mm': DEFSET, + 'Altitude_mm': calcExtraBottomThickness, 'SVG_Viewer': DEFSET, },'preface': { 'Meta': DEFSET, @@ -167,6 +188,7 @@ def getProfileInformation(): 'Perimeter_Feed_Rate_Multiplier_ratio': DEFSET, 'Perimeter_Flow_Rate_Multiplier_ratio': DEFSET, 'Travel_Feed_Rate_mm/s': storedSetting("travel_speed"), + 'Bottom_layer_flow_rate_ratio': calcBottomLayerFlowRateRatio, },'temperature': { 'Activate_Temperature': DEFSET,#ifSettingAboveZero('print_temperature'), 'Cooling_Rate_Celcius/second': DEFSET, diff --git a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py index 370a315dc6..cac112ef34 100644 --- a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py +++ b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py @@ -210,6 +210,8 @@ class SpeedRepository: settings.LabelSeparator().getFromRepository(self) self.travelFeedRatePerSecond = settings.FloatSpin().getFromValue( 2.0, 'Travel Feed Rate (mm/s):', self, 350.0, 250.0 ) self.executeTitle = 'Speed' + + self.bottomLayerFlowRateMultiplier = settings.FloatSpin().getFromValue(0.0, 'Bottom layer flow rate (ratio):', self, 10.0, 1.0) def execute(self): "Speed button has been clicked." @@ -246,6 +248,8 @@ class SpeedSkein: flowRate *= ((self.repository.objectFirstLayerFlowRatePerimeterMultiplier.value * (self.repository.objectFirstLayersLayerAmount.value - self.layerIndex)) + self.layerIndex) / self.repository.objectFirstLayersLayerAmount.value else: flowRate *= ((self.repository.objectFirstLayerFlowRateInfillMultiplier.value * (self.repository.objectFirstLayersLayerAmount.value - self.layerIndex)) + self.layerIndex) / self.repository.objectFirstLayersLayerAmount.value + if self.layerIndex == 0: + flowRate *= self.repository.bottomLayerFlowRateMultiplier.value if flowRate != self.oldFlowRate: self.distanceFeedRate.addLine('M108 S' + euclidean.getFourSignificantFigures(flowRate)) self.oldFlowRate = flowRate diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 870e02df86..d602ce4026 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -171,6 +171,10 @@ class mainWindow(configBase.configWindowBase): validators.validFloat(c, 0.0) c = configBase.SettingRow(right, "Enable cooling fan", 'fan_enabled', True, 'Enable the cooling fan during the print. The extra cooling from the cooling fan is essensial during faster prints.') + configBase.TitleRow(right, "Accuracy") + c = configBase.SettingRow(right, "Initial layer thickness (mm)", 'bottom_thickness', '0.0', 'Layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier. Set to 0.0 to have the bottom layer thickness the same as the other layers.') + validators.validFloat(c, 0.0) + nb.AddPage(alterationPanel.alterationPanel(nb), "Start/End-GCode") # load and slice buttons. diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 935cef7be5..3d36bcdc97 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -439,10 +439,13 @@ class PreviewGLCanvas(glcanvas.GLCanvas): layerThickness = 0.0 filamentRadius = float(profile.getProfileSetting('filament_diameter')) / 2 filamentArea = math.pi * filamentRadius * filamentRadius - lineWidth = float(profile.getProfileSetting('nozzle_size')) / 2 + lineWidth = float(profile.getProfileSetting('nozzle_size')) / 2 / 10 curLayerNum = 0 for layer in self.parent.gcode.layerList: + 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(): diff --git a/Cura/gui/printWindow.py b/Cura/gui/printWindow.py index b48650aded..46c7152bc6 100644 --- a/Cura/gui/printWindow.py +++ b/Cura/gui/printWindow.py @@ -199,7 +199,7 @@ class printWindow(wx.Frame): self.temp = float(re.search("[0-9\.]*", line.split('T:')[1]).group(0)) wx.CallAfter(self.UpdateProgress) if self.printIdx == None: - if line == '': #When we have a communication "timeout" and we're not sending gcode read the temperature. + if line == '': #When we have a communication "timeout" and we're not sending gcode, then read the temperature. self.machineCom.sendCommand("M105") else: if line.startswith("ok"): diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index 1b498be714..ece6ffaa27 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -214,6 +214,7 @@ class simpleModeWindow(configBase.configWindowBase): put('raft_margin', '5') put('raft_base_material_amount', '100') put('raft_interface_material_amount', '100') + put('bottom_thickness', '0.0') if self.printSupport.GetValue(): put('support', 'Exterior Only') @@ -234,6 +235,7 @@ class simpleModeWindow(configBase.configWindowBase): put('layer_height', '0.1') put('fill_density', '30') put('bottom_layer_speed', '15') + put('bottom_thickness', '0.2') elif self.printTypeJoris.GetValue(): put('wall_thickness', nozzle_size * 1.5) put('layer_height', '0.2') @@ -255,6 +257,7 @@ class simpleModeWindow(configBase.configWindowBase): put('enable_raft', 'True') put('skirt_line_count', '0') put('fan_layer', '1') + put('bottom_thickness', '0.0') #Create a progress panel and add it to the window. The progress panel will start the Skein operation. spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filename) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 213c57a519..e39d9257ea 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -61,6 +61,7 @@ profileDefaultSettings = { 'raft_margin': '5', 'raft_base_material_amount': '100', 'raft_interface_material_amount': '100', + 'bottom_thickness': '0.0', } preferencesDefaultSettings = { 'wizardDone': 'False', diff --git a/Cura/util/sliceRun.py b/Cura/util/sliceRun.py index 4813f359f2..0bc157fa1e 100644 --- a/Cura/util/sliceRun.py +++ b/Cura/util/sliceRun.py @@ -89,7 +89,7 @@ def getSliceCommand(filename): '--solid-layers', str(profile.calculateSolidLayerCount()), '--fill-density', str(float(profile.getProfileSetting('fill_density'))/100), '--fill-angle', '45', - '--fill-pattern', 'rectilinear', + '--fill-pattern', 'rectilinear', #rectilinear line concentric hilbertcurve archimedeanchords octagramspiral '--solid-fill-pattern', 'rectilinear', '--start-gcode', profile.getAlterationFilePath('start.gcode'), '--end-gcode', profile.getAlterationFilePath('end.gcode'), From 8a82f0c625cdee8141a3cab103a9c2de53e362bb Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 5 Apr 2012 18:00:22 +0200 Subject: [PATCH 05/11] Change default support material amount to 50%, this seems to make the support a lot easier to remove, without affecting quality. --- Cura/gui/simpleMode.py | 2 +- Cura/util/profile.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index ece6ffaa27..4e6262a221 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -205,7 +205,7 @@ class simpleModeWindow(configBase.configWindowBase): put('infill_type', 'Line') put('solid_top', 'True') put('fill_overlap', '15') - put('support_rate', '100') + put('support_rate', '50') put('support_distance', '0.5') put('joris', 'False') put('cool_min_feedrate', '5') diff --git a/Cura/util/profile.py b/Cura/util/profile.py index e39d9257ea..c63ef0c049 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -51,7 +51,7 @@ profileDefaultSettings = { 'infill_type': 'Line', 'solid_top': 'True', 'fill_overlap': '15', - 'support_rate': '100', + 'support_rate': '50', 'support_distance': '0.5', 'joris': 'False', 'enable_raft': 'False', From 251a96141e79f34246d0acbf86c2dcf1cf0518f1 Mon Sep 17 00:00:00 2001 From: Daid Date: Thu, 5 Apr 2012 22:35:52 +0200 Subject: [PATCH 06/11] Split up some OpenGL stuff from preview3d. Added swapXZ and swapYZ for rotating on the platform --- Cura/cura_sf/fabmetheus_utilities/settings.py | 2 + .../skeinforge_plugins/craft_plugins/carve.py | 17 +- Cura/gui/opengl.py | 94 +++++++++++ Cura/gui/preview3d.py | 159 ++++++------------ 4 files changed, 164 insertions(+), 108 deletions(-) create mode 100644 Cura/gui/opengl.py diff --git a/Cura/cura_sf/fabmetheus_utilities/settings.py b/Cura/cura_sf/fabmetheus_utilities/settings.py index 61cc77f388..fb19b972fa 100644 --- a/Cura/cura_sf/fabmetheus_utilities/settings.py +++ b/Cura/cura_sf/fabmetheus_utilities/settings.py @@ -101,6 +101,8 @@ def getProfileInformation(): 'FlipX': storedSetting("flip_x"), 'FlipY': storedSetting("flip_y"), 'FlipZ': storedSetting("flip_z"), + 'SwapXZ': storedSetting("swap_xz"), + 'SwapYZ': storedSetting("swap_yz"), 'Scale': storedSetting("model_scale"), 'Rotate': storedSetting("model_rotate_base"), },'scale': { 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 af138a998c..ae949b3daa 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 @@ -183,6 +183,8 @@ class CarveRepository: self.flipX = settings.BooleanSetting().getFromValue('FlipX', self, False) self.flipY = settings.BooleanSetting().getFromValue('FlipY', self, False) 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.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 ) @@ -210,6 +212,8 @@ class CarveSkein: scaleY = -scaleY if repository.flipZ.value == True: scaleZ = -scaleZ + swapXZ = repository.swapXZ.value + swapYZ = repository.swapYZ.value mat00 = math.cos(rotate) * scaleX mat01 =-math.sin(rotate) * scaleY mat10 = math.sin(rotate) * scaleX @@ -226,10 +230,17 @@ class CarveSkein: #v.y += self.machineCenter.y for i in xrange(0, len(carving.vertexes)): + x = carving.vertexes[i].x + y = carving.vertexes[i].y + z = carving.vertexes[i].z + if swapXZ: + x, z = z, x + if swapYZ: + y, z = z, y carving.vertexes[i] = Vector3( - carving.vertexes[i].x * mat00 + carving.vertexes[i].y * mat01, - carving.vertexes[i].x * mat10 + carving.vertexes[i].y * mat11, - carving.vertexes[i].z * scaleZ) + x * mat00 + y * mat01, + x * mat10 + y * mat11, + z * scaleZ) layerHeight = repository.layerHeight.value edgeWidth = repository.edgeWidth.value diff --git a/Cura/gui/opengl.py b/Cura/gui/opengl.py new file mode 100644 index 0000000000..583b141437 --- /dev/null +++ b/Cura/gui/opengl.py @@ -0,0 +1,94 @@ + +try: + import OpenGL + OpenGL.ERROR_CHECKING = False + from OpenGL.GLU import * + from OpenGL.GL import * + hasOpenGLlibs = True +except: + print "Failed to find PyOpenGL: http://pyopengl.sourceforge.net/" + hasOpenGLlibs = False + +def InitGL(window, view3D, zoom): + # set viewing projection + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + size = window.GetSize() + glViewport(0,0, size.GetWidth(), size.GetHeight()) + + glLightfv(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0]) + + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) + glEnable(GL_DEPTH_TEST) + glEnable(GL_CULL_FACE) + glDisable(GL_BLEND) + + glClearColor(0.0, 0.0, 0.0, 1.0) + glClearStencil(0) + glClearDepth(1.0) + + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + aspect = float(size.GetWidth()) / float(size.GetHeight()) + if view3D: + gluPerspective(90.0, aspect, 1.0, 1000.0) + else: + glOrtho(-aspect, aspect, -1, 1, -1000.0, 1000.0) + + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) + +def DrawMachine(machineSize): + glColor3f(1,1,1) + glLineWidth(4) + glDisable(GL_LIGHTING) + glBegin(GL_LINE_LOOP) + glVertex3f(0, 0, 0) + glVertex3f(machineSize.x, 0, 0) + glVertex3f(machineSize.x, machineSize.y, 0) + glVertex3f(0, machineSize.y, 0) + glEnd() + glLineWidth(2) + glBegin(GL_LINES) + for i in xrange(0, int(machineSize.x), 10): + glVertex3f(i, 0, 0) + glVertex3f(i, machineSize.y, 0) + for i in xrange(0, int(machineSize.y), 10): + glVertex3f(0, i, 0) + glVertex3f(machineSize.x, i, 0) + glEnd() + glLineWidth(1) + glBegin(GL_LINE_LOOP) + glVertex3f(0, 0, machineSize.z) + glVertex3f(machineSize.x, 0, machineSize.z) + glVertex3f(machineSize.x, machineSize.y, machineSize.z) + glVertex3f(0, machineSize.y, machineSize.z) + glEnd() + glBegin(GL_LINES) + glVertex3f(0, 0, 0) + glVertex3f(0, 0, machineSize.z) + glVertex3f(machineSize.x, 0, 0) + glVertex3f(machineSize.x, 0, machineSize.z) + glVertex3f(machineSize.x, machineSize.y, 0) + glVertex3f(machineSize.x, machineSize.y, machineSize.z) + glVertex3f(0, machineSize.y, 0) + glVertex3f(0, machineSize.y, machineSize.z) + glEnd() + +def DrawSTL(mesh): + for face in mesh.faces: + glBegin(GL_TRIANGLES) + v1 = face.v[0] + v2 = face.v[1] + v3 = face.v[2] + glNormal3f(face.normal.x, face.normal.y, face.normal.z) + glVertex3f(v1.x, v1.y, v1.z) + glVertex3f(v2.x, v2.y, v2.z) + glVertex3f(v3.x, v3.y, v3.z) + glNormal3f(-face.normal.x, -face.normal.y, -face.normal.z) + glVertex3f(v1.x, v1.y, v1.z) + glVertex3f(v3.x, v3.y, v3.z) + glVertex3f(v2.x, v2.y, v2.z) + glEnd() diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 3d36bcdc97..b081f86dbf 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -17,6 +17,8 @@ except: print "Failed to find PyOpenGL: http://pyopengl.sourceforge.net/" hasOpenGLlibs = False +from gui import opengl + from util import profile from util import gcodeInterpreter from util import stl @@ -75,6 +77,16 @@ class previewPanel(wx.Panel): self.flipZ.SetValue(profile.getProfileSetting('flip_z') == 'True') self.toolbar2.AddControl(self.flipZ) self.Bind(wx.EVT_CHECKBOX, self.OnFlipZClick, self.flipZ) + + self.swapXZ = wx.CheckBox(self.toolbar2, -1, "XZ") + self.swapXZ.SetValue(profile.getProfileSetting('swap_xz') == 'True') + self.toolbar2.AddControl(self.swapXZ) + self.Bind(wx.EVT_CHECKBOX, self.OnSwapXZClick, self.swapXZ) + + self.swapYZ = wx.CheckBox(self.toolbar2, -1, "YZ") + self.swapYZ.SetValue(profile.getProfileSetting('swap_yz') == 'True') + self.toolbar2.AddControl(self.swapYZ) + self.Bind(wx.EVT_CHECKBOX, self.OnSwapYZClick, self.swapYZ) self.toolbar2.InsertSeparator(self.toolbar2.GetToolsCount()) self.toolbar2.AddControl(wx.StaticText(self.toolbar2, -1, 'Scale')) @@ -126,6 +138,14 @@ class previewPanel(wx.Panel): profile.putProfileSetting('flip_z', str(self.flipZ.GetValue())) self.updateModelTransform() + def OnSwapXZClick(self, e): + profile.putProfileSetting('swap_xz', str(self.swapXZ.GetValue())) + self.updateModelTransform() + + def OnSwapYZClick(self, e): + profile.putProfileSetting('swap_yz', str(self.swapYZ.GetValue())) + self.updateModelTransform() + def OnMulXAddClick(self, e): profile.putProfileSetting('model_multiply_x', str(max(1, int(profile.getProfileSetting('model_multiply_x'))+1))) self.updateModelTransform() @@ -285,15 +305,24 @@ class previewPanel(wx.Panel): scaleY = -scaleY if profile.getProfileSetting('flip_z') == 'True': scaleZ = -scaleZ + swapXZ = profile.getProfileSetting('swap_xz') == 'True' + swapYZ = profile.getProfileSetting('swap_yz') == 'True' 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.triangleMesh.origonalVertexes)): - self.triangleMesh.vertexes[i].x = self.triangleMesh.origonalVertexes[i].x * mat00 + self.triangleMesh.origonalVertexes[i].y * mat01 - self.triangleMesh.vertexes[i].y = self.triangleMesh.origonalVertexes[i].x * mat10 + self.triangleMesh.origonalVertexes[i].y * mat11 - self.triangleMesh.vertexes[i].z = self.triangleMesh.origonalVertexes[i].z * scaleZ + x = self.triangleMesh.origonalVertexes[i].x + y = self.triangleMesh.origonalVertexes[i].y + z = self.triangleMesh.origonalVertexes[i].z + if swapXZ: + x, z = z, x + if swapYZ: + y, z = z, y + self.triangleMesh.vertexes[i].x = x * mat00 + y * mat01 + self.triangleMesh.vertexes[i].y = x * mat10 + y * mat11 + self.triangleMesh.vertexes[i].z = z * scaleZ for face in self.triangleMesh.faces: v1 = face.v[0] @@ -381,51 +410,24 @@ class PreviewGLCanvas(glcanvas.GLCanvas): dc.DrawText("No PyOpenGL installation found.\nNo preview window available.", 10, 10) return self.SetCurrent(self.context) - self.InitGL() + opengl.InitGL(self, self.view3D, self.zoom) + if self.view3D: + glTranslate(0,0,-self.zoom) + glRotate(-self.pitch, 1,0,0) + glRotate(self.yaw, 0,0,1) + if self.parent.triangleMesh != None: + glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2) + else: + glScale(1.0/self.zoom, 1.0/self.zoom, 1.0) + glTranslate(self.offsetX, self.offsetY, 0.0) + glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0) + self.OnDraw() self.SwapBuffers() def OnDraw(self): machineSize = self.parent.machineSize - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) - - glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0) - - glColor3f(1,1,1) - glLineWidth(4) - glDisable(GL_LIGHTING) - glBegin(GL_LINE_LOOP) - glVertex3f(0, 0, 0) - glVertex3f(machineSize.x, 0, 0) - glVertex3f(machineSize.x, machineSize.y, 0) - glVertex3f(0, machineSize.y, 0) - glEnd() - glLineWidth(2) - glBegin(GL_LINES) - for i in xrange(0, int(machineSize.x), 10): - glVertex3f(i, 0, 0) - glVertex3f(i, machineSize.y, 0) - for i in xrange(0, int(machineSize.y), 10): - glVertex3f(0, i, 0) - glVertex3f(machineSize.x, i, 0) - glEnd() - glLineWidth(1) - glBegin(GL_LINE_LOOP) - glVertex3f(0, 0, machineSize.z) - glVertex3f(machineSize.x, 0, machineSize.z) - glVertex3f(machineSize.x, machineSize.y, machineSize.z) - glVertex3f(0, machineSize.y, machineSize.z) - glEnd() - glBegin(GL_LINES) - glVertex3f(0, 0, 0) - glVertex3f(0, 0, machineSize.z) - glVertex3f(machineSize.x, 0, 0) - glVertex3f(machineSize.x, 0, machineSize.z) - glVertex3f(machineSize.x, machineSize.y, 0) - glVertex3f(machineSize.x, machineSize.y, machineSize.z) - glVertex3f(0, machineSize.y, 0) - glVertex3f(0, machineSize.y, machineSize.z) - glEnd() + opengl.DrawMachine(machineSize) if self.parent.gcode != None: if self.gcodeDisplayList == None: @@ -533,26 +535,16 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glTranslate(-(modelSize.x+10)*(multiX-1)/2,-(modelSize.y+10)*(multiY-1)/2, 0) for mx in xrange(0, multiX): for my in xrange(0, multiY): - for face in self.parent.triangleMesh.faces: - glPushMatrix() - glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0) - glBegin(GL_TRIANGLES) - v1 = face.v[0] - v2 = face.v[1] - v3 = face.v[2] - glNormal3f(face.normal.x, face.normal.y, face.normal.z) - glVertex3f(v1.x, v1.y, v1.z) - glVertex3f(v2.x, v2.y, v2.z) - glVertex3f(v3.x, v3.y, v3.z) - glNormal3f(-face.normal.x, -face.normal.y, -face.normal.z) - glVertex3f(v1.x, v1.y, v1.z) - glVertex3f(v3.x, v3.y, v3.z) - glVertex3f(v2.x, v2.y, v2.z) - glEnd() - glPopMatrix() + glPushMatrix() + glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0) + opengl.DrawSTL(self.parent.triangleMesh) + glPopMatrix() glPopMatrix() glEndList() + if self.viewMode == "Model - Transparent" or self.viewMode == "Mixed": + glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.5, 0.4, 0.3, 1.0]) + glLightfv(GL_LIGHT0, GL_AMBIENT, [0.1, 0.1, 0.1, 0.0]) #If we want transparent, then first render a solid black model to remove the printer size lines. if self.viewMode != "Mixed": glDisable(GL_BLEND) @@ -609,6 +601,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST) elif self.viewMode == "Model - Normal": + glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 0.8, 0.6, 1.0]) + glLightfv(GL_LIGHT0, GL_AMBIENT, [0.2, 0.2, 0.2, 0.0]) glEnable(GL_LIGHTING) glCallList(self.modelDisplayList) @@ -625,48 +619,3 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glEnd() glFlush() - - def InitGL(self): - # set viewing projection - glMatrixMode(GL_MODELVIEW) - glLoadIdentity() - size = self.GetSize() - glViewport(0,0, size.GetWidth(), size.GetHeight()) - - if self.viewMode == "Model - Transparent" or self.viewMode == "Mixed": - glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.5, 0.4, 0.3, 1.0]) - glLightfv(GL_LIGHT0, GL_AMBIENT, [0.1, 0.1, 0.1, 0.0]) - else: - glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 0.8, 0.6, 1.0]) - glLightfv(GL_LIGHT0, GL_AMBIENT, [0.2, 0.2, 0.2, 0.0]) - glLightfv(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0]) - - glEnable(GL_LIGHTING) - glEnable(GL_LIGHT0) - glEnable(GL_DEPTH_TEST) - glEnable(GL_CULL_FACE) - glDisable(GL_BLEND) - - glClearColor(0.0, 0.0, 0.0, 1.0) - glClearStencil(0) - glClearDepth(1.0) - - glMatrixMode(GL_PROJECTION) - glLoadIdentity() - aspect = float(self.GetSize().GetWidth()) / float(self.GetSize().GetHeight()) - if self.view3D: - gluPerspective(90.0, aspect, 1.0, 1000.0) - else: - glOrtho(-self.zoom * aspect, self.zoom * aspect, -self.zoom, self.zoom, -1000.0, 1000.0) - - glMatrixMode(GL_MODELVIEW) - glLoadIdentity() - if self.view3D: - glTranslate(0,0,-self.zoom) - glRotate(-self.pitch, 1,0,0) - glRotate(self.yaw, 0,0,1) - if self.parent.triangleMesh != None: - glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2) - else: - glTranslate(self.offsetX, self.offsetY, 0) - From bcf7466f9da939920f626e581ffc910078964c8f Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 6 Apr 2012 14:41:38 +0200 Subject: [PATCH 07/11] Updated advanced window (old name) to expert window (new name), was already called expert config in the GUI, just refactor in the code --- Cura/gui/{advancedConfig.py => expertConfig.py} | 6 +++--- Cura/gui/mainWindow.py | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) rename Cura/gui/{advancedConfig.py => expertConfig.py} (96%) diff --git a/Cura/gui/advancedConfig.py b/Cura/gui/expertConfig.py similarity index 96% rename from Cura/gui/advancedConfig.py rename to Cura/gui/expertConfig.py index 99c841f815..786c587f04 100644 --- a/Cura/gui/advancedConfig.py +++ b/Cura/gui/expertConfig.py @@ -10,10 +10,10 @@ from gui import sliceProgessPanel from gui import alterationPanel from gui import validators -class advancedConfigWindow(configBase.configWindowBase): - "Advanced configuration window" +class expertConfigWindow(configBase.configWindowBase): + "Expert configuration window" def __init__(self): - super(advancedConfigWindow, self).__init__(title='Expert config') + super(expertConfigWindow, self).__init__(title='Expert config') wx.EVT_CLOSE(self, self.OnClose) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index d602ce4026..1fe2650e9e 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -4,7 +4,7 @@ import __init__ import wx, os, platform, types, webbrowser from gui import configBase -from gui import advancedConfig +from gui import expertConfig from gui import preview3d from gui import sliceProgessPanel from gui import alterationPanel @@ -126,7 +126,7 @@ class mainWindow(configBase.configWindowBase): configBase.TitleRow(right, "Support") c = configBase.SettingRow(right, "Support type", 'support', ['None', 'Exterior Only', 'Everywhere', 'Empty Layers Only'], 'Type of support structure build.\nNone does not do any support.\nExterior only only creates support on the outside.\nEverywhere creates support even on the insides of the model.\nOnly on empty layers is for stacked objects.') - c = configBase.SettingRow(right, "Add raft", 'enable_raft', False, 'A raft is a few layers of lines below the bottom of the object. It prevents warping. Full raft settings can be found in the advanced settings.\nFor PLA this is usually not required. But if you print with ABS it is almost required.') + c = configBase.SettingRow(right, "Add raft", 'enable_raft', False, 'A raft is a few layers of lines below the bottom of the object. It prevents warping. Full raft settings can be found in the expert settings.\nFor PLA this is usually not required. But if you print with ABS it is almost required.') configBase.TitleRow(right, "Filament") c = configBase.SettingRow(right, "Diameter (mm)", 'filament_diameter', '2.89', 'Diameter of your filament, as accurately as possible.\nIf you cannot measure this value you will have to callibrate it, a higher number means less extrusion, a smaller number generates more extrusion.') @@ -291,9 +291,9 @@ class mainWindow(configBase.configWindowBase): printWindow.printFile(self.filename[: self.filename.rfind('.')] + "_export.gcode") def OnExpertOpen(self, e): - acw = advancedConfig.advancedConfigWindow() - acw.Centre() - acw.Show(True) + ecw = expertConfig.expertConfigWindow() + ecw.Centre() + ecw.Show(True) def removeSliceProgress(self, spp): self.progressPanelList.remove(spp) From 1ded2a5c18d017b4ba80b5b87f3e63b12ae9a524 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 6 Apr 2012 15:15:41 +0200 Subject: [PATCH 08/11] Added defaults for swap_xz and swap_yz --- Cura/gui/mainWindow.py | 3 ++- Cura/util/profile.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 1fe2650e9e..5740fc72df 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -96,7 +96,7 @@ class mainWindow(configBase.configWindowBase): configBase.TitleRow(left, "Accuracy") c = configBase.SettingRow(left, "Layer height (mm)", 'layer_height', '0.2', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.') validators.validFloat(c, 0.0) - validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 80 / 100), "Thicker layers then %.2fmm (80%% nozzle size) usually give bad results and are not recommended.") + validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 80.0 / 100.0), "Thicker layers then %.2fmm (80%% nozzle size) usually give bad results and are not recommended.") c = configBase.SettingRow(left, "Wall thickness (mm)", 'wall_thickness', '0.8', 'Thickness of the walls.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines.') validators.validFloat(c, 0.0) validators.wallThicknessValidator(c) @@ -174,6 +174,7 @@ class mainWindow(configBase.configWindowBase): configBase.TitleRow(right, "Accuracy") c = configBase.SettingRow(right, "Initial layer thickness (mm)", 'bottom_thickness', '0.0', 'Layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier. Set to 0.0 to have the bottom layer thickness the same as the other layers.') validators.validFloat(c, 0.0) + validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 3.0 / 4.0), "A bottom layer of more then %.2fmm (3/4 nozzle size) usually give bad results and is not recommended.") nb.AddPage(alterationPanel.alterationPanel(nb), "Start/End-GCode") diff --git a/Cura/util/profile.py b/Cura/util/profile.py index c63ef0c049..8229aeec43 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -42,6 +42,8 @@ profileDefaultSettings = { 'flip_x': 'False', 'flip_y': 'False', 'flip_z': 'False', + 'swap_xz': 'False', + 'swap_yz': 'False', 'model_rotate_base': '0', 'model_multiply_x': '1', 'model_multiply_y': '1', From 0626dae61cf7d5bd2b25ad367e3fde96e1c35fb7 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 6 Apr 2012 16:20:22 +0200 Subject: [PATCH 09/11] Update README to point people better to the right location --- README | 66 ------------------------------------------------------- README.md | 17 ++++++++++++++ 2 files changed, 17 insertions(+), 66 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index 7d879ae7b8..0000000000 --- a/README +++ /dev/null @@ -1,66 +0,0 @@ -For documentation check: https://github.com/daid/Cura/wiki -For downloads check: https://github.com/daid/Cura/downloads - -This package includes two programs: - -Pronterface: - - An application for both manually controlling and automatically feeding gcode to a 3D printer. - -Cura: - - A easy to use program for slicing STL files using SkeinForge. Cura can also visualize the 3D models in a variety of ways. - - On first run, Cura will ask to go through a set of calibration steps that will perform a series of operations on your 3D printer. One of those steps involves extruding a bit of filament where the filament is initially nearly fully extracted. As such, it you will probably need to run Pronterface first, heat up the extruder enough to be able to extract the filament and then use the Pronterface interface to reverse the extruder motor until the filament is at the right position (specifically, until the filament end is even with where the Bowden tube leaves the extuder motor assembly, on an Ultimaker). - -======== -BUILDING -======== - - ./package.sh - -The build script defaults to building for Windows. If you want to build for Mac OS X or Linux, choose one of: - - ./package.sh osx64 - ./package.sh linux - -Note that Mac OS X currently requires the manual installation of wxPython, PySerial, and PyOpenGL: - - sudo easy_install-2.7 pyserial - sudo easy_install-2.7 PyOpenGL - -You will need to download the appropriate wxPython Installer package and install it. It is available from: - - http://www.wxpython.org/download.php - -Specifically, install "wxPython2.9-osx-cocoa-py2.7" as it is the build that supports 64-bit execution. - -======= -RUNNING -======= - -Windows -------- - -Double-click skeinforge.bat and Printrun.bat. - -Mac OS X & Linux ----------------- - -Once built, the two apps -- Pronterface and Cura -- must be started from the command line (for now): - - # open a new terminal window and.... - cd osx64-Cura-NewUI-Beta4 - ./pronterface.sh & - ./Cura.sh & - -This will start both applications with their console logging output directed into the terminal window. - -======== -FIRMWARE -======== - -For Ultimaker users, it is highly recommended -- nearly required -- that you upgrade your firmware to the latest Marlin builds. See: - - http://wiki.ultimaker.com/Skeinforge_PyPy - diff --git a/README.md b/README.md new file mode 100644 index 0000000000..4bae532aec --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +Cura +==== + +If you are reading this, then you are looking at the *development* version of Cura. If you just want to use Cura look at the following location: https://github.com/daid/Cura/wiki + +Development +=========== + +Cura is developed in Python. Getting Cura up and running for development is not very difficult. If you copy the python and pypy from a release into your Cura development checkout then you can use Cura right away, just like you would with a release. +For development with git, check the help on github. Pull requests is the fastest way to get changes into Cura. + +Packaging +--------- + +Cura development comes with a script "package.sh", this script has been designed to run under unix like OSes (Linux, MacOS). Running it from sygwin is not a priority. +The "package.sh" script generates a final release package. You should not need it during development, unless you are changing the release process. If you want to distribute your own version of Cura, then the package.sh script will allow you to do that. + From b294aede47c24cf12dff15678913b933872b07b5 Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 6 Apr 2012 17:08:49 +0200 Subject: [PATCH 10/11] Added skin setting to advanced settings --- Cura/cura_sf/fabmetheus_utilities/settings.py | 12 ++++++------ Cura/gui/mainWindow.py | 1 + Cura/util/gcodeInterpreter.py | 2 +- Cura/util/profile.py | 1 + 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Cura/cura_sf/fabmetheus_utilities/settings.py b/Cura/cura_sf/fabmetheus_utilities/settings.py index fb19b972fa..e765bff0bf 100644 --- a/Cura/cura_sf/fabmetheus_utilities/settings.py +++ b/Cura/cura_sf/fabmetheus_utilities/settings.py @@ -270,12 +270,12 @@ def getProfileInformation(): 'Perimeter_Outside_Stretch_Over_Perimeter_Width_ratio': DEFSET, 'Stretch_From_Distance_Over_Perimeter_Width_ratio': DEFSET, },'skin': { - 'Activate_Skin': "False", - 'Horizontal_Infill_Divisions_integer': DEFSET, - 'Horizontal_Perimeter_Divisions_integer': DEFSET, - 'Vertical_Divisions_integer': DEFSET, - 'Hop_When_Extruding_Infill': DEFSET, - 'Layers_From_index': DEFSET, + 'Activate_Skin': storedSetting("enable_skin"), + 'Horizontal_Infill_Divisions_integer': "1", + 'Horizontal_Perimeter_Divisions_integer': "1", + 'Vertical_Divisions_integer': "2", + 'Hop_When_Extruding_Infill': "False", + 'Layers_From_index': "1", },'comb': { 'Activate_Comb': "True", 'Running_Jump_Space_mm': DEFSET, diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 5740fc72df..05170c8541 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -175,6 +175,7 @@ class mainWindow(configBase.configWindowBase): c = configBase.SettingRow(right, "Initial layer thickness (mm)", 'bottom_thickness', '0.0', 'Layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier. Set to 0.0 to have the bottom layer thickness the same as the other layers.') validators.validFloat(c, 0.0) validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 3.0 / 4.0), "A bottom layer of more then %.2fmm (3/4 nozzle size) usually give bad results and is not recommended.") + c = configBase.SettingRow(right, "Enable 'skin'", 'enable_skin', False, 'Skin prints the outer lines of the prints twice, each time with half the thickness. This gives the illusion of a higher print quality.') nb.AddPage(alterationPanel.alterationPanel(nb), "Start/End-GCode") diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 3570d49e99..0518be2731 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -105,7 +105,7 @@ class gcode(): else: pos.z += z * scale #Check if we have a new layer. - if oldPos.z != pos.z and startCodeDone: + if oldPos.z < pos.z and startCodeDone and len(currentLayer) > 0: self.layerList.append(currentLayer) currentLayer = [] if f is not None: diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 8229aeec43..34df82db33 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -56,6 +56,7 @@ profileDefaultSettings = { 'support_rate': '50', 'support_distance': '0.5', 'joris': 'False', + 'enable_skin': 'False', 'enable_raft': 'False', 'cool_min_feedrate': '5', 'bridge_speed': '100', From d0691018c211d1dbd500c0b3d363da8c5bd2f11d Mon Sep 17 00:00:00 2001 From: Daid Date: Sat, 7 Apr 2012 16:27:22 +0200 Subject: [PATCH 11/11] Fixed progress bar error when slicing with skin enabled. --- Cura/gui/sliceProgessPanel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Cura/gui/sliceProgessPanel.py b/Cura/gui/sliceProgessPanel.py index bdf2e82e0c..577b55454c 100644 --- a/Cura/gui/sliceProgessPanel.py +++ b/Cura/gui/sliceProgessPanel.py @@ -28,6 +28,7 @@ class sliceProgessPanel(wx.Panel): 'speed': 12.759510994, 'raft': 31.4580039978, 'skirt': 19.3436040878, + 'skin': 1.0, 'joris': 1.0, 'comb': 23.7805759907, 'cool': 27.148763895,