Fix resources, imports and indentations.

master
Ilya Kulakov 2012-12-05 19:14:06 +07:00
parent 132e6381ea
commit 377ea03c15
8 changed files with 2102 additions and 1971 deletions

View File

@ -9,10 +9,7 @@ The slicing code is the same as Skeinforge. But the UI has been revamped to be..
"""
from __future__ import absolute_import
import __init__
import sys
import platform
from optparse import OptionParser
from util import profile
@ -36,6 +33,7 @@ Reece.Arnott <http://forums.reprap.org/profile.php?12,152>
Wade <http://forums.reprap.org/profile.php?12,489>
Xsainnz <http://forums.reprap.org/profile.php?12,563>
Zach Hoeken <http://blog.zachhoeken.com/>
Ilya Kulakov (kulakov.ilya@gmail.com)
Organizations:
Ultimaker <http://www.ultimaker.com>
@ -45,12 +43,18 @@ __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agp
def main():
parser = OptionParser(usage="usage: %prog [options] <filename>.stl")
parser.add_option("-i", "--ini", action="store", type="string", dest="profileini", help="Load settings from a profile ini file")
parser.add_option("-P", "--project", action="store_true", dest="openprojectplanner", help="Open the project planner")
parser.add_option("-F", "--flat", action="store_true", dest="openflatslicer", help="Open the 2D SVG slicer (unfinished)")
parser.add_option("-r", "--print", action="store", type="string", dest="printfile", help="Open the printing interface, instead of the normal cura interface.")
parser.add_option("-p", "--profile", action="store", type="string", dest="profile", help="Internal option, do not use!")
parser.add_option("-s", "--slice", action="store_true", dest="slice", help="Slice the given files instead of opening them in Cura")
parser.add_option("-i", "--ini", action="store", type="string", dest="profileini",
help="Load settings from a profile ini file")
parser.add_option("-P", "--project", action="store_true", dest="openprojectplanner",
help="Open the project planner")
parser.add_option("-F", "--flat", action="store_true", dest="openflatslicer",
help="Open the 2D SVG slicer (unfinished)")
parser.add_option("-r", "--print", action="store", type="string", dest="printfile",
help="Open the printing interface, instead of the normal cura interface.")
parser.add_option("-p", "--profile", action="store", type="string", dest="profile",
help="Internal option, do not use!")
parser.add_option("-s", "--slice", action="store_true", dest="slice",
help="Slice the given files instead of opening them in Cura")
(options, args) = parser.parse_args()
if options.profile != None:
profile.loadGlobalProfileFromString(options.profile)
@ -58,30 +62,36 @@ def main():
profile.loadGlobalProfile(options.profileini)
if options.openprojectplanner != None:
from gui import projectPlanner
projectPlanner.main()
return
if options.openflatslicer != None:
from gui import flatSlicerWindow
flatSlicerWindow.main()
return
if options.printfile != None:
from gui import printWindow
printWindow.startPrintInterface(options.printfile)
return
if options.slice != None:
from util import sliceRun
sliceRun.runSlice(args)
else:
if len(args) > 0:
profile.putPreference('lastFile', ';'.join(args))
from gui import splashScreen
splashScreen.showSplash(mainWindowRunCallback)
def mainWindowRunCallback(splash):
from gui import mainWindow
mainWindow.main(splash)
if __name__ == '__main__':
main()

View File

@ -1,13 +1,18 @@
# coding=utf-8
from __future__ import absolute_import
import __init__
import wx, os, platform, types, webbrowser, threading, time, re
import webbrowser
import threading
import time
import wx
import wx.wizard
from gui import firmwareInstall
from gui import toolbarUtil
from util import machineCom
from util import profile
from util.resources import getPathForImage
class InfoBox(wx.Panel):
def __init__(self, parent):
@ -17,10 +22,15 @@ class InfoBox(wx.Panel):
self.sizer = wx.GridBagSizer(5, 5)
self.SetSizer(self.sizer)
self.attentionBitmap = toolbarUtil.getBitmapImage('attention.png')
self.errorBitmap = toolbarUtil.getBitmapImage('error.png')
self.readyBitmap = toolbarUtil.getBitmapImage('ready.png')
self.busyBitmap = [toolbarUtil.getBitmapImage('busy-0.png'), toolbarUtil.getBitmapImage('busy-1.png'), toolbarUtil.getBitmapImage('busy-2.png'), toolbarUtil.getBitmapImage('busy-3.png')]
self.attentionBitmap = wx.Bitmap(getPathForImage('attention.png'))
self.errorBitmap = wx.Bitmap(getPathForImage('error.png'))
self.readyBitmap = wx.Bitmap(getPathForImage('ready.png'))
self.busyBitmap = [
wx.Bitmap(getPathForImage('busy-0.png')),
wx.Bitmap(getPathForImage('busy-1.png')),
wx.Bitmap(getPathForImage('busy-2.png')),
wx.Bitmap(getPathForImage('busy-3.png'))
]
self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
self.text = wx.StaticText(self, -1, '')
@ -73,6 +83,7 @@ class InfoBox(wx.Panel):
self.busyState = None
self.bitmap.SetBitmap(self.attentionBitmap)
class InfoPage(wx.wizard.WizardPageSimple):
def __init__(self, parent, title):
wx.wizard.WizardPageSimple.__init__(self, parent)
@ -179,6 +190,7 @@ class InfoPage(wx.wizard.WizardPageSimple):
def StoreData(self):
pass
class FirstInfoPage(InfoPage):
def __init__(self, parent):
super(FirstInfoPage, self).__init__(parent, "First time run wizard")
@ -188,13 +200,16 @@ class FirstInfoPage(InfoPage):
self.AddText('* Configure Cura for your machine')
self.AddText('* Upgrade your firmware')
self.AddText('* Check if your machine is working safely')
#self.AddText('* Calibrate your machine')
#self.AddText('* Do your first print')
class RepRapInfoPage(InfoPage):
def __init__(self, parent):
super(RepRapInfoPage, self).__init__(parent, "RepRap information")
self.AddText('RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
self.AddText(
'RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
self.AddSeperator()
self.AddText('You will have to manually install Marlin or Sprinter firmware.')
@ -215,6 +230,7 @@ class RepRapInfoPage(InfoPage):
profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
class MachineSelectPage(InfoPage):
def __init__(self, parent):
super(MachineSelectPage, self).__init__(parent, "Select your machine")
@ -252,14 +268,18 @@ class MachineSelectPage(InfoPage):
profile.putProfileSetting('machine_center_y', '40')
profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
class FirmwareUpgradePage(InfoPage):
def __init__(self, parent):
super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
self.AddText('Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work.')
self.AddText(
'Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work.')
self.AddHiddenSeperator()
self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
self.AddText(
'The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
self.AddHiddenSeperator()
self.AddText('Cura requires these new features and thus\nyour firmware will most likely need to be upgraded.\nYou will get the chance to do so now.')
self.AddText(
'Cura requires these new features and thus\nyour firmware will most likely need to be upgraded.\nYou will get the chance to do so now.')
upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
@ -283,22 +303,24 @@ class FirmwareUpgradePage(InfoPage):
def OnUrlClick(self, e):
webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
class UltimakerCheckupPage(InfoPage):
def __init__(self, parent):
super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
self.checkBitmap = toolbarUtil.getBitmapImage('checkmark.png')
self.crossBitmap = toolbarUtil.getBitmapImage('cross.png')
self.unknownBitmap = toolbarUtil.getBitmapImage('question.png')
self.endStopNoneBitmap = toolbarUtil.getBitmapImage('endstop_none.png')
self.endStopXMinBitmap = toolbarUtil.getBitmapImage('endstop_xmin.png')
self.endStopXMaxBitmap = toolbarUtil.getBitmapImage('endstop_xmax.png')
self.endStopYMinBitmap = toolbarUtil.getBitmapImage('endstop_ymin.png')
self.endStopYMaxBitmap = toolbarUtil.getBitmapImage('endstop_ymax.png')
self.endStopZMinBitmap = toolbarUtil.getBitmapImage('endstop_zmin.png')
self.endStopZMaxBitmap = toolbarUtil.getBitmapImage('endstop_zmax.png')
self.checkBitmap = wx.Bitmap(getPathForImage('checkmark.png'))
self.crossBitmap = wx.Bitmap(getPathForImage('cross.png'))
self.unknownBitmap = wx.Bitmap(getPathForImage('question.png'))
self.endStopNoneBitmap = wx.Bitmap(getPathForImage('endstop_none.png'))
self.endStopXMinBitmap = wx.Bitmap(getPathForImage('endstop_xmin.png'))
self.endStopXMaxBitmap = wx.Bitmap(getPathForImage('endstop_xmax.png'))
self.endStopYMinBitmap = wx.Bitmap(getPathForImage('endstop_ymin.png'))
self.endStopYMaxBitmap = wx.Bitmap(getPathForImage('endstop_ymax.png'))
self.endStopZMinBitmap = wx.Bitmap(getPathForImage('endstop_zmin.png'))
self.endStopZMaxBitmap = wx.Bitmap(getPathForImage('endstop_zmax.png'))
self.AddText('It is a good idea to do a few sanity checks now on your Ultimaker.\nYou can skip these if you know your machine is functional.')
self.AddText(
'It is a good idea to do a few sanity checks now on your Ultimaker.\nYou can skip these if you know your machine is functional.')
b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
@ -469,6 +491,7 @@ class UltimakerCheckupPage(InfoPage):
def mcZChange(self, newZ):
pass
class UltimakerCalibrationPage(InfoPage):
def __init__(self, parent):
super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
@ -484,12 +507,14 @@ class UltimakerCalibrationPage(InfoPage):
self.AddSeperator()
self.AddText("First we need the diameter of your filament:")
self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
self.AddText("If you do not own digital Calipers that can measure\nat least 2 digits then use 2.89mm.\nWhich is the average diameter of most filament.")
self.AddText(
"If you do not own digital Calipers that can measure\nat least 2 digits then use 2.89mm.\nWhich is the average diameter of most filament.")
self.AddText("Note: This value can be changed later at any time.")
def StoreData(self):
profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
class UltimakerCalibrateStepsPerEPage(InfoPage):
def __init__(self, parent):
super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
@ -508,7 +533,8 @@ class UltimakerCalibrateStepsPerEPage(InfoPage):
self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
self.AddText("You can repeat these steps to get better calibration.")
self.AddSeperator()
self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
self.AddText(
"If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
self.heatButton = self.AddButton("Heatup for filament removal")
self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
@ -531,7 +557,9 @@ class UltimakerCalibrateStepsPerEPage(InfoPage):
currentEValue = float(self.stepsPerEInput.GetValue())
self.comm = machineCom.MachineCom()
if not self.comm.isOpen():
wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
wx.MessageBox(
"Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
'Printer error', wx.OK | wx.ICON_INFORMATION)
self.heatButton.Enable(True)
self.extrudeButton.Enable(True)
return
@ -561,7 +589,9 @@ class UltimakerCalibrateStepsPerEPage(InfoPage):
self.extrudeButton.Enable(False)
self.comm = machineCom.MachineCom()
if not self.comm.isOpen():
wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
wx.MessageBox(
"Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
'Printer error', wx.OK | wx.ICON_INFORMATION)
self.heatButton.Enable(True)
self.extrudeButton.Enable(True)
return
@ -577,7 +607,9 @@ class UltimakerCalibrateStepsPerEPage(InfoPage):
time.sleep(3)
self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
wx.MessageBox('Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)', 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
wx.MessageBox(
'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
'Machine heatup', wx.OK | wx.ICON_INFORMATION)
self.sendGCommand('M104 S0')
time.sleep(1)
self.comm.close()
@ -596,6 +628,7 @@ class UltimakerCalibrateStepsPerEPage(InfoPage):
def StoreData(self):
profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
class configWizard(wx.wizard.Wizard):
def __init__(self):
super(configWizard, self).__init__(None, -1, "Configuration Wizard")

View File

@ -1,14 +1,20 @@
import math, time, os
# coding=utf-8
from __future__ import absolute_import
import math
from util import meshLoader
from util import util3d
from util import profile
from util.resources import getPathForMesh
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/"
@ -61,7 +67,7 @@ def DrawMachine(machineSize):
global platformMesh
if platformMesh == None:
platformMesh = meshLoader.loadMesh(os.path.normpath(os.path.join(os.path.split(__file__)[0], "../images", 'ultimaker_platform.stl')))
platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
platformMesh.setRotateMirror(0, False, False, False, False, False)
DrawMesh(platformMesh)
@ -248,6 +254,7 @@ def DrawMachine(machineSize):
glPopMatrix()
glEnable(GL_DEPTH_TEST)
def ResetMatrixRotationAndScale():
matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
noZ = False
@ -278,6 +285,7 @@ def ResetMatrixRotationAndScale():
glLoadMatrixf(matrix)
return noZ
def DrawBox(vMin, vMax):
glBegin(GL_LINE_LOOP)
glVertex3f(vMin[0], vMin[1], vMin[2])
@ -303,6 +311,7 @@ def DrawBox(vMin, vMax):
glVertex3f(vMin[0], vMax[1], vMax[2])
glEnd()
def DrawMeshOutline(mesh):
glEnable(GL_CULL_FACE)
glEnableClientState(GL_VERTEX_ARRAY);
@ -317,6 +326,7 @@ def DrawMeshOutline(mesh):
glDisableClientState(GL_VERTEX_ARRAY)
def DrawMesh(mesh):
glEnable(GL_CULL_FACE)
glEnableClientState(GL_VERTEX_ARRAY);
@ -346,6 +356,7 @@ def DrawMesh(mesh):
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_NORMAL_ARRAY);
def DrawGCodeLayer(layer):
filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
filamentArea = math.pi * filamentRadius * filamentRadius

View File

@ -1,7 +1,14 @@
# coding=utf-8
from __future__ import absolute_import
import __init__
import wx, threading, re, subprocess, sys, os, time, platform
import threading
import re
import subprocess
import sys
import time
import platform
import wx
from wx.lib import buttons
from gui import icon
@ -12,6 +19,7 @@ from util import machineCom
from util import profile
from util import gcodeInterpreter
from util import power
from util.resources import getPathForImage
printWindowMonitorHandle = None
@ -21,6 +29,7 @@ def printFile(filename):
printWindowMonitorHandle = printProcessMonitor()
printWindowMonitorHandle.loadFile(filename)
def startPrintInterface(filename):
#startPrintInterface is called from the main script when we want the printer interface to run in a seperate process.
# It needs to run in a seperate process, as any running python code blocks the GCode sender pyton code (http://wiki.python.org/moin/GlobalInterpreterLock).
@ -34,6 +43,7 @@ def startPrintInterface(filename):
t.start()
app.MainLoop()
class printProcessMonitor():
def __init__(self):
self.handle = None
@ -45,7 +55,8 @@ class printProcessMonitor():
if platform.machine() == 'i386':
cmdList.insert(0, 'arch')
cmdList.insert(1, '-i386')
self.handle = subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.handle = subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
self.thread = threading.Thread(target=self.Monitor)
self.thread.start()
else:
@ -61,9 +72,10 @@ class printProcessMonitor():
self.handle = None
self.thread = None
class PrintCommandButton(buttons.GenBitmapButton):
def __init__(self, parent, commandList, bitmapFilename, size=(20, 20)):
self.bitmap = toolbarUtil.getBitmapImage(bitmapFilename)
self.bitmap = wx.Bitmap(getPathForImage(bitmapFilename))
super(PrintCommandButton, self).__init__(parent.directControlPanel, -1, self.bitmap, size=size)
self.commandList = commandList
@ -81,8 +93,10 @@ class PrintCommandButton(buttons.GenBitmapButton):
self.parent.machineCom.sendCommand(cmd)
e.Skip()
class printWindow(wx.Frame):
"Main user interface window"
def __init__(self):
super(printWindow, self).__init__(None, -1, title='Printing')
self.machineCom = None
@ -131,7 +145,8 @@ class printWindow(wx.Frame):
self.OnPowerWarningChange(None)
self.powerWarningTimer.Start(10000)
self.statsText = wx.StaticText(self.panel, -1, "Filament: ####.##m #.##g\nEstimated print time: #####:##\nMachine state:\nDetecting baudrateXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
self.statsText = wx.StaticText(self.panel, -1,
"Filament: ####.##m #.##g\nEstimated print time: #####:##\nMachine state:\nDetecting baudrateXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
boxsizer.Add(self.statsText, flag=wx.LEFT, border=5)
self.sizer.Add(boxsizer, pos=(0, 0), span=(7, 1), flag=wx.EXPAND)
@ -162,7 +177,8 @@ class printWindow(wx.Frame):
self.temperatureSelect = wx.SpinCtrl(self.temperaturePanel, -1, '0', size=(21 * 3, 21), style=wx.SP_ARROW_KEYS)
self.temperatureSelect.SetRange(0, 400)
self.bedTemperatureLabel = wx.StaticText(self.temperaturePanel, -1, "BedTemp:")
self.bedTemperatureSelect = wx.SpinCtrl(self.temperaturePanel, -1, '0', size=(21*3,21), style=wx.SP_ARROW_KEYS)
self.bedTemperatureSelect = wx.SpinCtrl(self.temperaturePanel, -1, '0', size=(21 * 3, 21),
style=wx.SP_ARROW_KEYS)
self.bedTemperatureSelect.SetRange(0, 400)
self.bedTemperatureLabel.Show(False)
self.bedTemperatureSelect.Show(False)
@ -211,8 +227,10 @@ class printWindow(wx.Frame):
sizer.Add(PrintCommandButton(self, ['G91', 'G1 Z-1 F200', 'G90'], 'print-move-z-1.png'), pos=(5, 8))
sizer.Add(PrintCommandButton(self, ['G91', 'G1 Z-10 F200', 'G90'], 'print-move-z-10.png'), pos=(6, 8))
sizer.Add(PrintCommandButton(self, ['G92 E0', 'G1 E2 F120'], 'extrude.png', size=(60,20)), pos=(1,10), span=(1,3), flag=wx.EXPAND)
sizer.Add(PrintCommandButton(self, ['G92 E0', 'G1 E-2 F120'], 'retract.png', size=(60,20)), pos=(2,10), span=(1,3), flag=wx.EXPAND)
sizer.Add(PrintCommandButton(self, ['G92 E0', 'G1 E2 F120'], 'extrude.png', size=(60, 20)), pos=(1, 10),
span=(1, 3), flag=wx.EXPAND)
sizer.Add(PrintCommandButton(self, ['G92 E0', 'G1 E-2 F120'], 'retract.png', size=(60, 20)), pos=(2, 10),
span=(1, 3), flag=wx.EXPAND)
nb.AddPage(self.directControlPanel, 'Jog')
@ -319,6 +337,7 @@ class printWindow(wx.Frame):
self.statsText.SetMinSize(self.statsText.GetSize())
self.UpdateButtonStates()
#self.UpdateProgress()
def OnCameraTimer(self, e):
@ -349,16 +368,20 @@ class printWindow(wx.Frame):
def UpdateButtonStates(self):
self.connectButton.Enable(self.machineCom == None or self.machineCom.isClosedOrError())
#self.loadButton.Enable(self.machineCom == None or not (self.machineCom.isPrinting() or self.machineCom.isPaused()))
self.printButton.Enable(self.machineCom != None and self.machineCom.isOperational() and not (self.machineCom.isPrinting() or self.machineCom.isPaused()))
self.pauseButton.Enable(self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused()))
self.printButton.Enable(self.machineCom != None and self.machineCom.isOperational() and not (
self.machineCom.isPrinting() or self.machineCom.isPaused()))
self.pauseButton.Enable(
self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused()))
if self.machineCom != None and self.machineCom.isPaused():
self.pauseButton.SetLabel('Resume')
else:
self.pauseButton.SetLabel('Pause')
self.cancelButton.Enable(self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused()))
self.cancelButton.Enable(
self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused()))
self.temperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational())
self.bedTemperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational())
self.directControlPanel.Enable(self.machineCom != None and self.machineCom.isOperational() and not self.machineCom.isPrinting())
self.directControlPanel.Enable(
self.machineCom != None and self.machineCom.isOperational() and not self.machineCom.isPrinting())
self.machineLogButton.Show(self.machineCom != None and self.machineCom.isClosedOrError())
if self.cam != None:
for button in self.cam.buttons:
@ -369,11 +392,13 @@ class printWindow(wx.Frame):
if self.gcode == None:
status += "Loading gcode...\n"
else:
status += "Filament: %.2fm %.2fg\n" % (self.gcode.extrusionAmount / 1000, self.gcode.calculateWeight() * 1000)
status += "Filament: %.2fm %.2fg\n" % (
self.gcode.extrusionAmount / 1000, self.gcode.calculateWeight() * 1000)
cost = self.gcode.calculateCost()
if cost != False:
status += "Filament cost: %s\n" % (cost)
status += "Estimated print time: %02d:%02d\n" % (int(self.gcode.totalMoveTimeMinute / 60), int(self.gcode.totalMoveTimeMinute % 60))
status += "Estimated print time: %02d:%02d\n" % (
int(self.gcode.totalMoveTimeMinute / 60), int(self.gcode.totalMoveTimeMinute % 60))
if self.machineCom == None or not self.machineCom.isPrinting():
self.progress.SetValue(0)
if self.gcodeList != None:
@ -381,7 +406,8 @@ class printWindow(wx.Frame):
else:
printTime = self.machineCom.getPrintTime() / 60
printTimeLeft = self.machineCom.getPrintTimeRemainingEstimate()
status += 'Line: %d/%d %d%%\n' % (self.machineCom.getPrintPos(), len(self.gcodeList), self.machineCom.getPrintPos() * 100 / len(self.gcodeList))
status += 'Line: %d/%d %d%%\n' % (self.machineCom.getPrintPos(), len(self.gcodeList),
self.machineCom.getPrintPos() * 100 / len(self.gcodeList))
if self.currentZ > 0:
status += 'Height: %0.1f\n' % (self.currentZ)
status += 'Print time: %02d:%02d\n' % (int(printTime / 60), int(printTime % 60))
@ -583,6 +609,7 @@ class printWindow(wx.Frame):
wx.CallAfter(self.cam.takeNewImage)
wx.CallAfter(self.camPreview.Refresh)
class temperatureGraph(wx.Panel):
def __init__(self, parent):
super(temperatureGraph, self).__init__(parent)
@ -698,6 +725,7 @@ class temperatureGraph(wx.Panel):
self.points.append((temp, tempSP, bedTemp, bedTempSP, time.time()))
wx.CallAfter(self.UpdateDrawing)
class LogWindow(wx.Frame):
def __init__(self, logText):
super(LogWindow, self).__init__(None, title="Machine log")

View File

@ -1,18 +1,15 @@
import sys, os
#We only need the core here, which speeds up the import. As we want to show the splashscreen ASAP.
import wx._core
# coding=utf-8
from __future__ import absolute_import
import wx._core #We only need the core here, which speeds up the import. As we want to show the splashscreen ASAP.
from util.resources import getPathForImage
def getBitmapImage(filename):
#The frozen executable has the script files in a zip, so we need to exit another level to get to our images.
if hasattr(sys, 'frozen'):
return wx.Bitmap(os.path.normpath(os.path.join(os.path.split(__file__)[0], "../../images", filename)))
else:
return wx.Bitmap(os.path.normpath(os.path.join(os.path.split(__file__)[0], "../images", filename)))
class splashScreen(wx.SplashScreen):
def __init__(self, callback):
self.callback = callback
bitmap = getBitmapImage("splash.png")
bitmap = wx.Bitmap(getPathForImage('splash.png'))
super(splashScreen, self).__init__(bitmap, wx.SPLASH_CENTRE_ON_SCREEN, 0, None)
wx.CallAfter(self.DoCallback)
@ -20,20 +17,23 @@ class splashScreen(wx.SplashScreen):
self.callback(self)
self.Destroy()
def showSplash(callback):
app = wx.App(False)
splashScreen(callback)
app.MainLoop()
def testCallback(splashscreen):
print "Callback!"
import time
time.sleep(2)
print "!Callback"
def main():
showSplash(testCallback)
if __name__ == u'__main__':
main()

View File

@ -1,24 +1,19 @@
# coding=utf-8
from __future__ import absolute_import
from __future__ import division
import os, sys
import wx
from wx.lib import buttons
from util import profile
from util.resources import getPathForImage
#######################################################
# toolbarUtil contains help classes and functions for
# toolbar buttons.
#######################################################
def getBitmapImage(filename):
#The frozen executable has the script files in a zip, so we need to exit another level to get to our images.
if hasattr(sys, 'frozen'):
return wx.Bitmap(os.path.normpath(os.path.join(os.path.split(__file__)[0], "../../images", filename)))
else:
return wx.Bitmap(os.path.normpath(os.path.join(os.path.split(__file__)[0], "../images", filename)))
class Toolbar(wx.ToolBar):
def __init__(self, parent):
super(Toolbar, self).__init__(parent, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
@ -52,11 +47,12 @@ class Toolbar(wx.ToolBar):
sx, sy = control.GetSizeTuple()
popup.SetPosition((x, y + sy))
class ToggleButton(buttons.GenBitmapToggleButton):
def __init__(self, parent, profileSetting, bitmapFilenameOn, bitmapFilenameOff,
helpText='', id=-1, callback=None, size=(20, 20)):
self.bitmapOn = getBitmapImage(bitmapFilenameOn)
self.bitmapOff = getBitmapImage(bitmapFilenameOff)
self.bitmapOn = wx.Bitmap(getPathForImage(bitmapFilenameOn))
self.bitmapOff = wx.Bitmap(getPathForImage(bitmapFilenameOff))
super(ToggleButton, self).__init__(parent, id, self.bitmapOff, size=size)
@ -117,11 +113,12 @@ class ToggleButton(buttons.GenBitmapToggleButton):
self.Refresh()
event.Skip()
class RadioButton(buttons.GenBitmapButton):
def __init__(self, parent, group, bitmapFilenameOn, bitmapFilenameOff,
helpText='', id=-1, callback=None, size=(20, 20)):
self.bitmapOn = getBitmapImage(bitmapFilenameOn)
self.bitmapOff = getBitmapImage(bitmapFilenameOff)
self.bitmapOn = wx.Bitmap(getPathForImage(bitmapFilenameOn))
self.bitmapOff = wx.Bitmap(getPathForImage(bitmapFilenameOff))
super(RadioButton, self).__init__(parent, id, self.bitmapOff, size=size)
@ -179,10 +176,11 @@ class RadioButton(buttons.GenBitmapButton):
self.Refresh()
event.Skip()
class NormalButton(buttons.GenBitmapButton):
def __init__(self, parent, callback, bitmapFilename,
helpText='', id=-1, size=(20, 20)):
self.bitmap = getBitmapImage(bitmapFilename)
self.bitmap = wx.Bitmap(getPathForImage(bitmapFilename))
super(NormalButton, self).__init__(parent, id, self.bitmap, size=size)
self.helpText = helpText

View File

@ -1,7 +1,15 @@
import os, glob, subprocess, platform
# coding=utf-8
from __future__ import absolute_import
import os
import glob
import subprocess
import platform
import wx
from util import profile
from util.resources import getPathForImage
from gui import toolbarUtil
try:
@ -26,6 +34,7 @@ def hasWebcamSupport():
return False
return True
def getFFMPEGpath():
if platform.system() == "Windows":
return os.path.normpath(os.path.join(os.path.split(__file__)[0], "../ffmpeg.exe"))
@ -33,11 +42,12 @@ def getFFMPEGpath():
return '/usr/bin/ffmpeg'
return os.path.normpath(os.path.join(os.path.split(__file__)[0], "../ffmpeg"))
class webcam(object):
def __init__(self):
self._cam = None
self._overlayImage = toolbarUtil.getBitmapImage("cura-overlay.png")
self._overlayUltimaker = toolbarUtil.getBitmapImage("ultimaker-overlay.png")
self._overlayImage = wx.Bitmap(getPathForImage('cura-overlay.png'))
self._overlayUltimaker = wx.Bitmap(getPathForImage('ultimaker-overlay.png'))
if cv != None:
self._cam = highgui.cvCreateCameraCapture(-1)
elif win32vidcap != None:
@ -100,13 +110,15 @@ class webcam(object):
dc.SelectObject(bitmap)
dc.DrawBitmap(self._overlayImage, bitmap.GetWidth() - self._overlayImage.GetWidth() - 5, 5, True)
if profile.getPreference('machine_type') == 'ultimaker':
dc.DrawBitmap(self._overlayUltimaker, (bitmap.GetWidth() - self._overlayUltimaker.GetWidth()) / 2, bitmap.GetHeight() - self._overlayUltimaker.GetHeight() - 5, True)
dc.DrawBitmap(self._overlayUltimaker, (bitmap.GetWidth() - self._overlayUltimaker.GetWidth()) / 2,
bitmap.GetHeight() - self._overlayUltimaker.GetHeight() - 5, True)
dc.SelectObject(wx.NullBitmap)
self._bitmap = bitmap
if self._doTimelaps:
filename = os.path.normpath(os.path.join(os.path.split(__file__)[0], "../__tmp_snap", "__tmp_snap_%04d.jpg" % (self._snapshotCount)))
filename = os.path.normpath(os.path.join(os.path.split(__file__)[0], "../__tmp_snap",
"__tmp_snap_%04d.jpg" % (self._snapshotCount)))
self._snapshotCount += 1
bitmap.SaveFile(filename, wx.BITMAP_TYPE_JPEG)
@ -127,8 +139,11 @@ class webcam(object):
def endTimelaps(self):
if self._doTimelaps:
ffmpeg = getFFMPEGpath()
basePath = os.path.normpath(os.path.join(os.path.split(__file__)[0], "../__tmp_snap", "__tmp_snap_%04d.jpg"))
subprocess.call([ffmpeg, '-r', '12.5', '-i', basePath, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', '25', '-y', '-b:v', '1500k', '-f', 'vob', self._timelapsFilename])
basePath = os.path.normpath(
os.path.join(os.path.split(__file__)[0], "../__tmp_snap", "__tmp_snap_%04d.jpg"))
subprocess.call(
[ffmpeg, '-r', '12.5', '-i', basePath, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', '25', '-y',
'-b:v', '1500k', '-f', 'vob', self._timelapsFilename])
self._doTimelaps = False
def _cleanTempDir(self):

36
Cura/util/resources.py Normal file
View File

@ -0,0 +1,36 @@
# coding=utf-8
from __future__ import absolute_import
import os
import sys
__all__ = ['getPathForResource', 'getPathForImage', 'getPathForMesh']
if sys.platform.startswith('darwin'):
if hasattr(sys, 'frozen'):
from Foundation import *
imagesPath = os.path.join(NSBundle.mainBundle().resourcePath(), 'images')
meshesPath = os.path.join(NSBundle.mainBundle().resourcePath(), 'images')
else:
imagesPath = os.path.join(os.path.dirname(__file__), "../images")
meshesPath = os.path.join(os.path.dirname(__file__), "../images")
else:
if hasattr(sys, 'frozen'):
imagesPath = os.path.join(os.path.dirname(__file__), "../../images")
meshesPath = os.path.join(os.path.dirname(__file__), "../../images")
else:
imagesPath = os.path.join(os.path.dirname(__file__), "../images")
meshesPath = os.path.join(os.path.dirname(__file__), "../images")
def getPathForResource(dir, resource_name):
assert os.path.isdir(dir), "{p} is not a directory".format(p=dir)
path = os.path.normpath(os.path.join(dir, resource_name))
assert os.path.isfile(path), "{p} is not a file.".format(p=path)
return path
def getPathForImage(name):
return getPathForResource(imagesPath, name)
def getPathForMesh(name):
return getPathForResource(meshesPath, name)