chiark / gitweb /
Added online stat collection, added dropdown 3D button.
authordaid303 <daid303@gmail.com>
Mon, 18 Feb 2013 16:07:40 +0000 (17:07 +0100)
committerdaid303 <daid303@gmail.com>
Mon, 18 Feb 2013 16:07:40 +0000 (17:07 +0100)
Cura/gui/configWizard.py
Cura/gui/preferencesDialog.py
Cura/gui/preview3d.py
Cura/gui/util/opengl.py
Cura/gui/util/openglGui.py
Cura/slice/__main__.py
Cura/util/meshLoaders/obj.py
Cura/util/profile.py

index 54e8eb22dfd666391b71e0062a2b3b91ee1e9500..dab0ea08991494b3eee539c48f7ae8d069b153d7 100644 (file)
@@ -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):
index 55e73ccc3a221989e67d6cd5d427503ed5aab184..5744dc0115a0a732bc440f1f7adbcd271856b017 100644 (file)
@@ -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)
index eaf8fd5ac7a445ba8b972294d43c5251963c3b28..31963a3c68b6dccc2d8e2f91134f292ae700c4e7 100644 (file)
@@ -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()
        
index ef3a0db8d6510dec344ae61fdaa03beb6c9e6be2..87d8508032da1690d49890a37d0941959e6e40de 100644 (file)
@@ -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)))
index d718b47239ebe0589d7f13790552d6ce49c66b36..c5c965ef20de7e2d59a07a0e7a93be0ac1924c67 100644 (file)
@@ -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()
index 573920bd1e4edd68a12fc220183aacb81356081f..66f20db12e9bcab3556cbf4e8274a0224bc959cc 100644 (file)
@@ -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):
index d6b2cd7ddde0b806d9db134d3334e0c854dc9a32..e8c7dfa77a2ba6f4387393a44beacc256e79f3cb 100644 (file)
@@ -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()
index ff9988bd61ff507d440c31b8c84276b6bdbd9c85..4e43f9ef2762941ea5980d9cd8a7f0a54a4a7408 100644 (file)
@@ -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',
 }
 
 #########################################################