From 806d891dc85aad843bcb7e47dd28b0e6445b8153 Mon Sep 17 00:00:00 2001 From: daid303 Date: Mon, 18 Feb 2013 17:07:40 +0100 Subject: [PATCH] Added online stat collection, added dropdown 3D button. --- Cura/gui/configWizard.py | 11 ++++- Cura/gui/preferencesDialog.py | 1 + Cura/gui/preview3d.py | 20 ++++++--- Cura/gui/util/opengl.py | 6 +++ Cura/gui/util/openglGui.py | 83 ++++++++++++++++++++++++++++++++++- Cura/slice/__main__.py | 28 ++++++++++++ Cura/util/meshLoaders/obj.py | 6 +++ Cura/util/profile.py | 3 ++ 8 files changed, 148 insertions(+), 10 deletions(-) diff --git a/Cura/gui/configWizard.py b/Cura/gui/configWizard.py index 54e8eb22..dab0ea08 100644 --- a/Cura/gui/configWizard.py +++ b/Cura/gui/configWizard.py @@ -263,6 +263,12 @@ class MachineSelectPage(InfoPage): self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect) self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)") self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect) + self.AddSeperator() + self.AddText('The collection of anonymous usage information helps with the continued improvement of Cura.') + self.AddText('This does NOT submit your models online nor gathers any privacy related information.') + self.SubmitUserStats = self.AddCheckbox('Submit anonymous usage information:') + self.AddText('For full details see: http://wiki.ultimaker.com/Cura:stats') + self.SubmitUserStats.SetValue(True) def OnUltimakerSelect(self, e): wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage) @@ -286,7 +292,10 @@ class MachineSelectPage(InfoPage): profile.putPreference('startMode', 'Normal') profile.putProfileSetting('nozzle_size', '0.5') profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2) - + if self.SubmitUserStats.GetValue(): + profile.putPreference('submit_slice_information', 'True') + else: + profile.putPreference('submit_slice_information', 'False') class SelectParts(InfoPage): def __init__(self, parent): diff --git a/Cura/gui/preferencesDialog.py b/Cura/gui/preferencesDialog.py index 55e73ccc..5744dc01 100644 --- a/Cura/gui/preferencesDialog.py +++ b/Cura/gui/preferencesDialog.py @@ -68,6 +68,7 @@ class preferencesDialog(wx.Frame): configBase.TitleRow(right, 'Cura settings') c = configBase.SettingRow(right, 'Check for updates', 'check_for_updates', True, 'Check for newer versions of Cura on startup', type = 'preference') + c = configBase.SettingRow(right, 'Send usage statistics', 'submit_slice_information', True, 'Submit anonymous usage information to improve next versions of Cura', type = 'preference') self.okButton = wx.Button(right, -1, 'Ok') right.GetSizer().Add(self.okButton, (right.GetSizer().GetRows(), 0), flag=wx.BOTTOM, border=5) diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index eaf8fd5a..31963a3c 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -148,6 +148,8 @@ class previewPanel(wx.Panel): openglGui.glLabel(self.scaleForm, 'Uniform scale', (0,8)) self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None) + self.viewSelection = openglGui.glComboButton(self.glCanvas, 'View mode', [0,1,2,3,4], ['3D Model', 'Transparent', 'X-Ray', 'Overhang', 'Layers'], (-1,0), self.OnViewChange) + self.OnViewChange() self.OnToolSelect() self.returnToModelViewAndUpdateModel() @@ -478,19 +480,23 @@ class previewPanel(wx.Panel): self.Update() def OnViewChange(self): - if self.normalViewButton.GetValue(): + selection = self.viewSelection.getValue() + self.glCanvas.drawSteepOverhang = False + self.glCanvas.drawBorders = self.showBorderButton.GetValue() + if selection == 0: self.glCanvas.viewMode = "Normal" - elif self.transparentViewButton.GetValue(): + elif selection == 1: self.glCanvas.viewMode = "Transparent" - elif self.xrayViewButton.GetValue(): + elif selection == 2: self.glCanvas.viewMode = "X-Ray" - elif self.gcodeViewButton.GetValue(): + elif selection == 3: + self.glCanvas.viewMode = "Normal" + self.glCanvas.drawSteepOverhang = True + elif selection == 4: self.layerSpin.SetValue(self.layerSpin.GetMax()) self.glCanvas.viewMode = "GCode" - elif self.mixedViewButton.GetValue(): + elif selection == 5: self.glCanvas.viewMode = "Mixed" - self.glCanvas.drawBorders = self.showBorderButton.GetValue() - self.glCanvas.drawSteepOverhang = self.showSteepOverhang.GetValue() self.updateToolbar() self.glCanvas.Refresh() diff --git a/Cura/gui/util/opengl.py b/Cura/gui/util/opengl.py index ef3a0db8..87d85080 100644 --- a/Cura/gui/util/opengl.py +++ b/Cura/gui/util/opengl.py @@ -207,6 +207,12 @@ def glDrawStringLeft(s): for c in s: glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c)) +def glDrawStringRight(s): + glRasterPos2f(0, 0) + glBitmap(0,0,0,0, -glGetStringSize(s)[0], 0, None) + for c in s: + glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c)) + def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport): npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4))) npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4))) diff --git a/Cura/gui/util/openglGui.py b/Cura/gui/util/openglGui.py index d718b472..c5c965ef 100644 --- a/Cura/gui/util/openglGui.py +++ b/Cura/gui/util/openglGui.py @@ -48,6 +48,12 @@ class glGuiControl(object): def setFocus(self): return False + def hasFocus(self): + return self._base._focus == self + + def OnKeyChar(self, key): + pass + class glGuiContainer(glGuiControl): def __init__(self, parent, pos): self._glGuiControlList = [] @@ -353,6 +359,7 @@ class glRadioButton(glButton): self._selected = value def _onRadioSelect(self): + self._base._focus = None for ctrl in self._group: if ctrl != self: ctrl.setSelected(False) @@ -362,6 +369,78 @@ class glRadioButton(glButton): self.setSelected(True) self._radioCallback() +class glComboButton(glButton): + def __init__(self, parent, tooltip, imageIDs, tooltips, pos, callback): + super(glComboButton, self).__init__(parent, imageIDs[0], tooltip, pos, self._onComboOpenSelect) + self._imageIDs = imageIDs + self._tooltips = tooltips + self._comboCallback = callback + self._selection = 0 + + def _onComboOpenSelect(self): + self._base._focus = self + + def draw(self): + if self._hidden: + return + self._selected = self.hasFocus() + super(glComboButton, self).draw() + if not self._selected: + return + + bs = self._base._buttonSize / 2 + pos = self._getPixelPos() + + glPushMatrix() + glTranslatef(pos[0]+bs*0.5, pos[1] + bs*0.5, 0) + glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture) + glScalef(bs, bs, bs) + for n in xrange(0, len(self._imageIDs)): + cx = (self._imageIDs[n] % 4) / 4 + cy = int(self._imageIDs[n] / 4) / 4 + glEnable(GL_TEXTURE_2D) + glTranslatef(0, 1, 0) + if self._disabled: + glColor4ub(128,128,128,128) + else: + glColor4ub(255,255,255,255) + glBegin(GL_QUADS) + glTexCoord2f(cx+0.25, cy) + glVertex2f( 0.5,-0.5) + glTexCoord2f(cx, cy) + glVertex2f(-0.5,-0.5) + glTexCoord2f(cx, cy+0.25) + glVertex2f(-0.5, 0.5) + glTexCoord2f(cx+0.25, cy+0.25) + glVertex2f( 0.5, 0.5) + glEnd() + glDisable(GL_TEXTURE_2D) + + glPushMatrix() + glColor4ub(0,0,0,255) + glTranslatef(-0.55, 0.1, 0) + opengl.glDrawStringRight(self._tooltips[n]) + glPopMatrix() + glPopMatrix() + + def getValue(self): + return self._selection + + def OnMouseDown(self, x, y): + if self._hidden or self._disabled: + return False + if self.hasFocus(): + bs = self._base._buttonSize / 2 + pos = self._getPixelPos() + if 0 <= x - pos[0] <= bs and 0 <= y - pos[1] - bs <= bs * len(self._imageIDs): + self._selection = int((y - pos[1] - bs) / bs) + self._imageID = self._imageIDs[self._selection] + self._base._focus = None + self._comboCallback() + return True + return super(glComboButton, self).OnMouseDown(x, y) + + class glFrame(glGuiContainer): def __init__(self, parent, pos): super(glFrame, self).__init__(parent, pos) @@ -508,7 +587,7 @@ class glNumberCtrl(glGuiControl): glPushMatrix() glTranslatef(x, y, 0) - if self._base._focus == self: + if self.hasFocus(): glColor4ub(255,255,255,255) else: glColor4ub(255,255,255,192) @@ -526,7 +605,7 @@ class glNumberCtrl(glGuiControl): glTranslate(5, h - 5, 0) glColor4ub(0,0,0,255) opengl.glDrawStringLeft(self._value) - if self._base._focus == self: + if self.hasFocus(): glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0) opengl.glDrawStringLeft('|') glPopMatrix() diff --git a/Cura/slice/__main__.py b/Cura/slice/__main__.py index 573920bd..66f20db1 100644 --- a/Cura/slice/__main__.py +++ b/Cura/slice/__main__.py @@ -4,6 +4,10 @@ from optparse import OptionParser import sys import re import os +import urllib +import urllib2 +import platform +import hashlib if not hasattr(sys, 'frozen'): cura_sf_path = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "./cura_sf/")) @@ -86,6 +90,30 @@ def main(): if ret is not None: print ret print "Finalizing %s" % (os.path.basename(options.output)) + if profile.getPreference('submit_slice_information') == 'True': + filenames = fixUTF8(args[idx + 1]).split('|') + for filename in filenames: + m = hashlib.sha512() + f = open(filename, "rb") + while True: + chunk = f.read(1024) + if not chunk: + break + m.update(chunk) + f.close() + data = { + 'processor': platform.processor(), + 'machine': platform.machine(), + 'platform': platform.platform(), + 'profile': profile.getGlobalProfileString(), + 'modelhash': m.hexdigest(), + } + try: + f = urllib2.urlopen("http://software.ultimaker.com/upload_stats.php", data = urllib.urlencode(data), timeout = 5); + f.read() + f.close() + except: + pass def stitchMultiExtruder(outputList, resultFile): diff --git a/Cura/util/meshLoaders/obj.py b/Cura/util/meshLoaders/obj.py index d6b2cd7d..e8c7dfa7 100644 --- a/Cura/util/meshLoaders/obj.py +++ b/Cura/util/meshLoaders/obj.py @@ -26,10 +26,16 @@ class objModel(mesh.mesh): self._prepareVertexCount(len(faceList) * 3) for f in faceList: i = f[0] - 1 + if i < 0 or i >= len(vertexList): + i = 0 self.addVertex(vertexList[i][0], vertexList[i][1], vertexList[i][2]) i = f[1] - 1 + if i < 0 or i >= len(vertexList): + i = 0 self.addVertex(vertexList[i][0], vertexList[i][1], vertexList[i][2]) i = f[2] - 1 + if i < 0 or i >= len(vertexList): + i = 0 self.addVertex(vertexList[i][0], vertexList[i][1], vertexList[i][2]) self._postProcessAfterLoad() diff --git a/Cura/util/profile.py b/Cura/util/profile.py index ff9988bd..4e43f9ef 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -150,6 +150,7 @@ preferencesDefaultSettings = { 'machine_center_is_zero': 'False', 'ultimaker_extruder_upgrade': 'False', 'has_heated_bed': 'False', + 'reprap_name': 'RepRap', 'extruder_amount': '1', 'extruder_offset_x1': '-22.0', 'extruder_offset_y1': '0.0', @@ -170,6 +171,7 @@ preferencesDefaultSettings = { 'sdpath': '', 'sdshortnames': 'False', 'check_for_updates': 'True', + 'submit_slice_information': 'False', 'planner_always_autoplace': 'True', 'extruder_head_size_min_x': '75.0', @@ -188,6 +190,7 @@ preferencesDefaultSettings = { 'window_pos_y': '-1', 'window_width': '-1', 'window_height': '-1', + 'window_normal_sash': '320', } ######################################################### -- 2.30.2