From 7b02b1661abfc24a8f81229125c35e0928b0168e Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 20 Sep 2012 14:28:44 +0200 Subject: [PATCH 1/6] Cut up long moves into sections of 1cm, to reduce the impact of buffering lots of long moves. --- .../skeinforge_plugins/craft_plugins/dimension.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py index cbe8f5b3..bea35534 100644 --- a/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py +++ b/Cura/cura_sf/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py @@ -234,6 +234,16 @@ class DimensionSkein: location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) if self.oldLocation != None: distance = abs( location - self.oldLocation ) + if distance > 11.0: + extra = '' + while distance > 11.0: + self.oldLocation.z = location.z + self.oldLocation += (location - self.oldLocation) / distance * 10.0 + distance -= 10.0 + e = self.getExtrusionDistanceString(10.0, splitLine) + extra += self.distanceFeedRate.getLinearGcodeMovementWithFeedRate(self.feedRateMinute, self.oldLocation.dropAxis(), self.oldLocation.z) + e + '\n' + print extra, line, distance + line = extra + line self.oldLocation = location else: if self.oldLocation == None: From 19cdf497337cebf84dafa1a070d78e37cab38058 Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 20 Sep 2012 15:17:49 +0200 Subject: [PATCH 2/6] Add a tools menu for the project planner and the batch runner, makes them easier to find then filling up the file menu. --- Cura/gui/mainWindow.py | 24 ++++++++++++------------ Cura/gui/simpleMode.py | 11 ++++------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index f20b01b4..6e75d076 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -61,28 +61,28 @@ class mainWindow(configBase.configWindowBase): i = fileMenu.Append(-1, 'Reset Profile to default') self.Bind(wx.EVT_MENU, self.OnResetProfile, i) fileMenu.AppendSeparator() - i = fileMenu.Append(-1, 'Batch run...') - self.Bind(wx.EVT_MENU, self.OnBatchRun, i) i = fileMenu.Append(-1, 'Preferences...') self.Bind(wx.EVT_MENU, self.OnPreferences, i) fileMenu.AppendSeparator() - i = fileMenu.Append(-1, 'Open project planner...') - self.Bind(wx.EVT_MENU, self.OnProjectPlanner, i) - fileMenu.AppendSeparator() i = fileMenu.Append(wx.ID_EXIT, 'Quit') self.Bind(wx.EVT_MENU, self.OnQuit, i) menubar.Append(fileMenu, '&File') - - simpleMenu = wx.Menu() - i = simpleMenu.Append(-1, 'Switch to Quickprint...') + + toolsMenu = wx.Menu() + i = toolsMenu.Append(-1, 'Switch to Quickprint...') self.Bind(wx.EVT_MENU, self.OnSimpleSwitch, i) - menubar.Append(simpleMenu, 'Simple') + toolsMenu.AppendSeparator() + i = toolsMenu.Append(-1, 'Batch run...') + self.Bind(wx.EVT_MENU, self.OnBatchRun, i) + i = toolsMenu.Append(-1, 'Project planner...') + self.Bind(wx.EVT_MENU, self.OnProjectPlanner, i) +# i = toolsMenu.Append(-1, 'Open SVG (2D) slicer...') +# self.Bind(wx.EVT_MENU, self.OnSVGSlicerOpen, i) + menubar.Append(toolsMenu, 'Tools') expertMenu = wx.Menu() i = expertMenu.Append(-1, 'Open expert settings...') self.Bind(wx.EVT_MENU, self.OnExpertOpen, i) -# i = expertMenu.Append(-1, 'Open SVG (2D) slicer...') -# self.Bind(wx.EVT_MENU, self.OnSVGSlicerOpen, i) expertMenu.AppendSeparator() i = expertMenu.Append(-1, 'Install default Marlin firmware') self.Bind(wx.EVT_MENU, self.OnDefaultMarlinFirmware, i) @@ -95,7 +95,7 @@ class mainWindow(configBase.configWindowBase): helpMenu = wx.Menu() i = helpMenu.Append(-1, 'Online documentation...') - self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/wiki'), i) + self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i) i = helpMenu.Append(-1, 'Report a problem...') self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i) menubar.Append(helpMenu, 'Help') diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index c5092657..b133fa1a 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -36,17 +36,14 @@ class simpleModeWindow(configBase.configWindowBase): self.Bind(wx.EVT_MENU, self.OnQuit, i) menubar.Append(fileMenu, '&File') - expertMenu = wx.Menu() - i = expertMenu.Append(-1, 'Switch to Normal mode...') + toolsMenu = wx.Menu() + i = toolsMenu.Append(-1, 'Switch to Normal mode...') self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i) - expertMenu.AppendSeparator() - i = expertMenu.Append(-1, 'ReRun first run wizard...') - self.Bind(wx.EVT_MENU, self.OnFirstRunWizard, i) - menubar.Append(expertMenu, 'Expert') + menubar.Append(toolsMenu, 'Tools') helpMenu = wx.Menu() i = helpMenu.Append(-1, 'Online documentation...') - self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/wiki'), i) + self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i) i = helpMenu.Append(-1, 'Report a problem...') self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i) menubar.Append(helpMenu, 'Help') From 5678f916179692fa243d3273f2cf4353d9d16848 Mon Sep 17 00:00:00 2001 From: daid Date: Thu, 20 Sep 2012 16:34:08 +0200 Subject: [PATCH 3/6] . --- Cura/util/machineCom.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cura/util/machineCom.py b/Cura/util/machineCom.py index 384a03b7..80297719 100644 --- a/Cura/util/machineCom.py +++ b/Cura/util/machineCom.py @@ -366,8 +366,9 @@ class MachineCom(object): return self._log('Send: %s' % (cmd)) try: - self._serial.write(cmd) - self._serial.write('\n') + #TODO: This can throw a write timeout exception, but we do not want timeout on writes. Find a fix for this. + # Oddly enough, the write timeout is not even set and thus we should not get a write timeout. + self._serial.write(cmd + '\n') except: self._log("Unexpected error while writing serial port: %s" % (getExceptionString())) self._errorValue = getExceptionString() From 399fc1bf06dcb1f1275123430364124a8c3b0f6a Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 21 Sep 2012 14:27:08 +0200 Subject: [PATCH 4/6] Added Attribution, which is needed by the license of the example model I added. --- Cura/example/Attribution.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Cura/example/Attribution.txt diff --git a/Cura/example/Attribution.txt b/Cura/example/Attribution.txt new file mode 100644 index 00000000..09c83d60 --- /dev/null +++ b/Cura/example/Attribution.txt @@ -0,0 +1,8 @@ +All the models in this example directory can be found on Thingiverse (www.thingiverse.com), a site for sharing digital designs for physical objects. Sharing is fun! + +The below models are shared under the CC BY-NC 3.0 license (http://creativecommons.org/licenses/by-nc/3.0/), and can be shared and used freely for none-commercial purposes: + +* UltimakerRobotCourseMesh.stl: Ultimaker Robot Low Poly by polymaker + http://www.thingiverse.com/thing:14472 + Derivative of Ultimaker Robot by Martijn: http://www.thingiverse.com/thing:11551 + From b1a7647c6e3ff1f3c52a0cd84d966acc48ab376a Mon Sep 17 00:00:00 2001 From: daid Date: Fri, 21 Sep 2012 16:21:59 +0200 Subject: [PATCH 5/6] Fix a bug with the project planners "all at once" mode. --- Cura/gui/projectPlanner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 619a4e25..63a88cf2 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -1003,7 +1003,9 @@ class ProjectSliceProgressWindow(wx.Frame): wx.CallAfter(self.progressGauge2.SetValue, self.actionList.index(action) + 1) resultFile.write(';TYPE:CUSTOM\n') - resultFile.write('G1 Z%f F%f\n' % (self.actionList[-1].clearZ, profile.getProfileSettingFloat('max_z_speed') * 60)) + if len(self.actionList) > 1: + #only move to higher Z if we have sliced more then 1 object. This solves the "move into print after printing" problem with the print-all-at-once option. + resultFile.write('G1 Z%f F%f\n' % (self.actionList[-1].clearZ, profile.getProfileSettingFloat('max_z_speed') * 60)) resultFile.write(profile.getAlterationFileContents('end.gcode')) resultFile.close() From b785dccec199b2a4b686a76b3f75bed99795bd2a Mon Sep 17 00:00:00 2001 From: daid Date: Mon, 24 Sep 2012 16:37:52 +0200 Subject: [PATCH 6/6] It is a bit tricked, but you can now rotate the model with a circle around the model in a drag/drop way. --- Cura/gui/preview3d.py | 91 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 13 deletions(-) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 97f8a3f2..3899d08f 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -273,7 +273,7 @@ class previewPanel(wx.Panel): size = (self.objectsMaxV - self.objectsMinV) * scale if size[0] > self.machineSize.x or size[1] > self.machineSize.y or size[2] > self.machineSize.z: self.OnScaleMax(None) - self.glCanvas.zoom = numpy.max(size) * 1.7 + self.glCanvas.zoom = numpy.max(size) * 2.5 self.errorList = [] wx.CallAfter(self.updateToolbar) wx.CallAfter(self.glCanvas.Refresh) @@ -419,6 +419,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas): 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]] self.oldX = 0 self.oldY = 0 + self.dragType = '' + self.tempRotate = 0 def updateProfileToControls(self): self.objColor[0] = profile.getPreferenceColour('model_colour') @@ -427,23 +429,54 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.objColor[3] = profile.getPreferenceColour('model_colour3') def OnMouseMotion(self,e): + size = (self.parent.objectsMaxV - self.parent.objectsMinV) + sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1])) + + p0 = numpy.array(gluUnProject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)) + p1 = numpy.array(gluUnProject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)) + cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2])) + cursorXY = math.sqrt((cursorZ0[0] * cursorZ0[0]) + (cursorZ0[1] * cursorZ0[1])) + if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3: + self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) + else: + self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) + if e.Dragging() and e.LeftIsDown(): - if self.view3D: - self.yaw += e.GetX() - self.oldX - self.pitch -= e.GetY() - self.oldY - if self.pitch > 170: - self.pitch = 170 - if self.pitch < 10: - self.pitch = 10 - else: - self.offsetX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2 - self.offsetY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2 - + if self.dragType == '': + #Define the drag type depending on the cursor position. + if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3: + self.dragType = 'modelRotate' + self.dragStart = math.atan2(cursorZ0[0], cursorZ0[1]) + else: + self.dragType = 'viewRotate' + + if self.dragType == 'viewRotate': + if self.view3D: + self.yaw += e.GetX() - self.oldX + self.pitch -= e.GetY() - self.oldY + if self.pitch > 170: + self.pitch = 170 + if self.pitch < 10: + self.pitch = 10 + else: + self.offsetX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2 + self.offsetY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2 + elif self.dragType == 'modelRotate': + angle = math.atan2(cursorZ0[0], cursorZ0[1]) + diff = self.dragStart - angle + self.tempRotate = diff * 180 / math.pi #Workaround for buggy ATI cards. size = self.GetSizeTuple() self.SetSize((size[0]+1, size[1])) self.SetSize((size[0], size[1])) self.Refresh() + else: + if self.tempRotate != 0: + profile.putProfileSetting('model_rotate_base', profile.getProfileSettingFloat('model_rotate_base') + self.tempRotate) + self.parent.updateModelTransform() + self.tempRotate = 0 + + self.dragType = '' if e.Dragging() and e.RightIsDown(): self.zoom += e.GetY() - self.oldY if self.zoom < 1: @@ -451,6 +484,9 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.Refresh() self.oldX = e.GetX() self.oldY = e.GetY() + + #self.Refresh() + def OnMouseWheel(self,e): self.zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0 @@ -482,10 +518,15 @@ class PreviewGLCanvas(glcanvas.GLCanvas): 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[2] * profile.getProfileSettingFloat('model_scale') / 2) + glTranslate(0,0,-(self.parent.objectsMaxV[2]-self.parent.objectsMinV[2]) * profile.getProfileSettingFloat('model_scale') / 2) else: glScale(1.0/self.zoom, 1.0/self.zoom, 1.0) glTranslate(self.offsetX, self.offsetY, 0.0) + + self.viewport = glGetIntegerv(GL_VIEWPORT); + self.modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX); + self.projMatrix = glGetDoublev(GL_PROJECTION_MATRIX); + glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0) self.OnDraw() @@ -529,6 +570,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): self.drawModel(obj) glColor3f(1.0,1.0,1.0) glClear(GL_DEPTH_BUFFER_BIT) + glPopMatrix() if self.parent.gcode != None and (self.viewMode == "GCode" or self.viewMode == "Mixed"): @@ -654,6 +696,28 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glEnd() glEnable(GL_DEPTH_TEST) opengl.DrawMachine(machineSize) + + glPushMatrix() + glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0) + + #Draw the rotate circle + glDisable(GL_LIGHTING) + glDisable(GL_CULL_FACE) + glEnable(GL_BLEND) + glBegin(GL_TRIANGLE_STRIP) + size = (self.parent.objectsMaxV - self.parent.objectsMinV) + sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1])) + for i in xrange(0, 64+1): + f = i if i < 64/2 else 64 - i + glColor4ub(255,int(f*255/(64/2)),0,128) + glVertex3f(sizeXY * 0.7 * math.cos(i/32.0*math.pi), sizeXY * 0.7 * math.sin(i/32.0*math.pi),0.1) + glColor4ub( 0,128,0,128) + glVertex3f((sizeXY * 0.7 + 3) * math.cos(i/32.0*math.pi), (sizeXY * 0.7 + 3) * math.sin(i/32.0*math.pi),0.1) + glEnd() + glEnable(GL_CULL_FACE) + + glPopMatrix() + glFlush() def drawModel(self, obj): @@ -662,6 +726,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): modelScale = profile.getProfileSettingFloat('model_scale') modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale glPushMatrix() + glRotate(self.tempRotate, 0, 0, 1) glTranslate(-(modelSize[0]+10)*(multiX-1)/2,-(modelSize[1]+10)*(multiY-1)/2, 0) for mx in xrange(0, multiX): for my in xrange(0, multiY):