Merge branch 'master' of github.com:daid/Cura

This commit is contained in:
Daid 2012-05-04 19:28:29 +02:00
commit 7d9bf5adfa
14 changed files with 210 additions and 157 deletions

View File

@ -19,6 +19,8 @@ class GcodeTextArea(wx.stc.StyledTextCtrl):
self.IndicatorSetForeground(0, "#0000FF")
self.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE)
self.IndicatorSetForeground(1, "#FF0000")
self.SetWrapMode(wx.stc.STC_WRAP_NONE)
self.SetScrollWidth(1000)
#GCodes and MCodes as supported by Marlin
#GCode 21 is not really supported by Marlin, but we still do not report it as error as it's often used.

View File

@ -25,9 +25,108 @@ from util import stl
from util import sliceRun
from util import gcodeInterpreter
class Action():
class Action(object):
pass
class ProjectObject(stl.stlModel):
def __init__(self, filename):
super(ProjectObject, self).__init__()
self.load(filename)
self.filename = filename
self.scale = 1.0
self.rotate = 0.0
self.flipX = False
self.flipY = False
self.flipZ = False
self.swapXZ = False
self.swapYZ = False
self.extruder = 0
self.modelDisplayList = None
self.modelDirty = False
self.origonalVertexes = list(self.vertexes)
for i in xrange(0, len(self.origonalVertexes)):
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
self.getMinimumZ()
self.centerX = -self.getMinimum().x + 5
self.centerY = -self.getMinimum().y + 5
self.updateModelTransform()
self.centerX = -self.getMinimum().x + 5
self.centerY = -self.getMinimum().y + 5
def updateModelTransform(self):
rotate = self.rotate / 180.0 * math.pi
scaleX = 1.0
scaleY = 1.0
scaleZ = 1.0
if self.flipX:
scaleX = -scaleX
if self.flipY:
scaleY = -scaleY
if self.flipZ:
scaleZ = -scaleZ
swapXZ = self.swapXZ
swapYZ = self.swapYZ
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.origonalVertexes)):
x = self.origonalVertexes[i].x
y = self.origonalVertexes[i].y
z = self.origonalVertexes[i].z
if swapXZ:
x, z = z, x
if swapYZ:
y, z = z, y
self.vertexes[i].x = x * mat00 + y * mat01
self.vertexes[i].y = x * mat10 + y * mat11
self.vertexes[i].z = z * scaleZ
for face in self.faces:
v1 = face.v[0]
v2 = face.v[1]
v3 = face.v[2]
face.normal = (v2 - v1).cross(v3 - v1)
face.normal.normalize()
minZ = self.getMinimumZ()
minV = self.getMinimum()
maxV = self.getMaximum()
for v in self.vertexes:
v.z -= minZ
v.x -= minV.x + (maxV.x - minV.x) / 2
v.y -= minV.y + (maxV.y - minV.y) / 2
self.getMinimumZ()
self.modelDirty = True
def clone(self):
p = ProjectObject(self.filename)
p.centerX = self.centerX + 5
p.centerY = self.centerY + 5
p.filename = self.filename
p.scale = self.scale
p.rotate = self.rotate
p.flipX = self.flipX
p.flipY = self.flipY
p.flipZ = self.flipZ
p.swapXZ = self.swapXZ
p.swapYZ = self.swapYZ
p.extruder = self.extruder
p.updateModelTransform()
return p
class projectPlanner(wx.Frame):
"Main user interface window"
def __init__(self):
@ -62,6 +161,14 @@ class projectPlanner(wx.Frame):
toolbarUtil.NormalButton(self.toolbar, self.OnQuit, 'exit.png', 'Close project planner')
self.toolbar.Realize()
self.toolbar2 = toolbarUtil.Toolbar(self)
toolbarUtil.NormalButton(self.toolbar2, self.OnAddModel, 'object-add.png', 'Add model')
toolbarUtil.NormalButton(self.toolbar2, self.OnRemModel, 'object-remove.png', 'Remove model')
toolbarUtil.NormalButton(self.toolbar2, self.OnMoveUp, 'move-up.png', 'Move model up in print list')
toolbarUtil.NormalButton(self.toolbar2, self.OnMoveDown, 'move-down.png', 'Move model down in print list')
toolbarUtil.NormalButton(self.toolbar2, self.OnCopy, 'copy.png', 'Make a copy of the current selected object')
self.toolbar2.Realize()
sizer = wx.GridBagSizer(2,2)
self.SetSizer(sizer)
@ -72,7 +179,8 @@ class projectPlanner(wx.Frame):
self.sliceButton = wx.Button(self, -1, "Slice")
self.autoPlaceButton = wx.Button(self, -1, "Auto Place")
sizer.Add(self.toolbar, (0,0), span=(1,3), flag=wx.EXPAND)
sizer.Add(self.toolbar, (0,0), span=(1,1), flag=wx.EXPAND)
sizer.Add(self.toolbar2, (0,1), span=(1,2), flag=wx.EXPAND)
sizer.Add(self.preview, (1,0), span=(4,1), flag=wx.EXPAND)
sizer.Add(self.listbox, (1,1), span=(1,2), flag=wx.EXPAND)
sizer.Add(self.addButton, (2,1), span=(1,1))
@ -156,9 +264,7 @@ class projectPlanner(wx.Frame):
while cp.has_section('model_%d' % (i)):
section = 'model_%d' % (i)
item = stl.stlModel()
item.filename = unicode(cp.get(section, 'filename'), "utf-8")
self.loadModelFile(item)
item = ProjectObject(unicode(cp.get(section, 'filename'), "utf-8"))
item.centerX = float(cp.get(section, 'centerX'))
item.centerY = float(cp.get(section, 'centerY'))
item.scale = float(cp.get(section, 'scale'))
@ -170,6 +276,7 @@ class projectPlanner(wx.Frame):
item.swapYZ = cp.get(section, 'swapYZ') == 'True'
if cp.has_option(section, 'extruder'):
item.extuder = int(cp.get(section, 'extruder'))-1
item.updateModelTransform()
i += 1
self.list.append(item)
@ -177,6 +284,7 @@ class projectPlanner(wx.Frame):
self.listbox.SetSelection(len(self.list)-1)
self.OnListSelect(None)
self.preview.Refresh()
dlg.Destroy()
@ -209,32 +317,67 @@ class projectPlanner(wx.Frame):
dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")
if dlg.ShowModal() == wx.ID_OK:
for filename in dlg.GetPaths():
item = stl.stlModel()
item.filename=filename
item = ProjectObject(filename)
profile.putPreference('lastFile', item.filename)
if not(os.path.exists(item.filename)):
return
self.loadModelFile(item)
self.list.append(item)
self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1])
self.listbox.SetSelection(len(self.list)-1)
self.OnListSelect(None)
self.selection = item
self._updateListbox()
self.preview.Refresh()
dlg.Destroy()
def OnRemModel(self, e):
if self.selection == None:
return
self.list.remove(self.selection)
i = self.listbox.GetSelection()
self.listbox.Delete(i)
if len(self.list) > i:
self.listbox.SetSelection(i)
elif len(self.list) > 0:
self.listbox.SetSelection(len(self.list) - 1)
self.selection = None
self.OnListSelect(None)
self._updateListbox()
self.preview.Refresh()
def OnMoveUp(self, e):
if self.selection == None:
return
i = self.listbox.GetSelection()
if i == 0:
return
self.list.remove(self.selection)
self.list.insert(i-1, self.selection)
self._updateListbox()
self.preview.Refresh()
def OnMoveDown(self, e):
if self.selection == None:
return
i = self.listbox.GetSelection()
if i == len(self.list) - 1:
return
self.list.remove(self.selection)
self.list.insert(i+1, self.selection)
self._updateListbox()
self.preview.Refresh()
def OnCopy(self, e):
if self.selection == None:
return
item = self.selection.clone()
self.list.append(item)
self.selection = item
self._updateListbox()
self.preview.Refresh()
def _updateListbox(self):
self.listbox.Clear()
for item in self.list:
self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1])
if self.selection in self.list:
self.listbox.SetSelection(self.list.index(self.selection))
elif len(self.list) > 0:
self.selection = self.list[0]
self.listbox.SetSelection(0)
else:
self.selection = None
self.listbox.SetSelection(-1)
def OnAutoPlace(self, e):
bestAllowedSize = int(self.machineSize.y)
bestArea = self._doAutoPlace(bestAllowedSize)
@ -333,32 +476,6 @@ class projectPlanner(wx.Frame):
pspw.Centre()
pspw.Show(True)
def loadModelFile(self, item):
item.load(item.filename)
item.origonalVertexes = list(item.vertexes)
for i in xrange(0, len(item.origonalVertexes)):
item.origonalVertexes[i] = item.origonalVertexes[i].copy()
item.getMinimumZ()
item.centerX = -item.getMinimum().x + 5
item.centerY = -item.getMinimum().y + 5
item.scale = 1.0
item.rotate = 0.0
item.flipX = False
item.flipY = False
item.flipZ = False
item.swapXZ = False
item.swapYZ = False
item.extruder = 0
item.modelDisplayList = None
item.modelDirty = False
self.updateModelTransform(item)
item.centerX = -item.getMinimum().x + 5
item.centerY = -item.getMinimum().y + 5
def OnScaleChange(self, e):
if self.selection == None:
return
@ -372,7 +489,8 @@ class projectPlanner(wx.Frame):
if self.selection == None:
return
self.selection.rotate = float(self.rotateCtrl.GetValue())
self.updateModelTransform(self.selection)
self.selection.updateModelTransform()
self.preview.Refresh()
def OnExtruderChange(self, e):
if self.selection == None:
@ -380,57 +498,6 @@ class projectPlanner(wx.Frame):
self.selection.extruder = int(self.extruderCtrl.GetValue()) - 1
self.preview.Refresh()
def updateModelTransform(self, item):
rotate = item.rotate / 180.0 * math.pi
scaleX = 1.0
scaleY = 1.0
scaleZ = 1.0
if item.flipX:
scaleX = -scaleX
if item.flipY:
scaleY = -scaleY
if item.flipZ:
scaleZ = -scaleZ
swapXZ = item.swapXZ
swapYZ = item.swapYZ
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(item.origonalVertexes)):
x = item.origonalVertexes[i].x
y = item.origonalVertexes[i].y
z = item.origonalVertexes[i].z
if swapXZ:
x, z = z, x
if swapYZ:
y, z = z, y
item.vertexes[i].x = x * mat00 + y * mat01
item.vertexes[i].y = x * mat10 + y * mat11
item.vertexes[i].z = z * scaleZ
for face in item.faces:
v1 = face.v[0]
v2 = face.v[1]
v3 = face.v[2]
face.normal = (v2 - v1).cross(v3 - v1)
face.normal.normalize()
self.moveModel(item)
def moveModel(self, item):
minZ = item.getMinimumZ()
min = item.getMinimum()
max = item.getMaximum()
for v in item.vertexes:
v.z -= minZ
v.x -= min.x + (max.x - min.x) / 2
v.y -= min.y + (max.y - min.y) / 2
item.getMinimumZ()
item.modelDirty = True
self.preview.Refresh()
class PreviewGLCanvas(glcanvas.GLCanvas):
def __init__(self, parent):
attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
@ -637,28 +704,6 @@ class ProjectSliceProgressWindow(wx.Frame):
self.startTime = time.time()
self.sliceStartTime = time.time()
#How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left.
# TODO: Duplicate with sliceProgressPanel, move to sliceRun.
self.sliceStepTimeFactor = {
'start': 3.3713991642,
'slice': 15.4984838963,
'preface': 5.17178297043,
'inset': 116.362634182,
'fill': 215.702672005,
'multiply': 21.9536788464,
'speed': 12.759510994,
'raft': 31.4580039978,
'skirt': 19.3436040878,
'skin': 1.0,
'joris': 1.0,
'comb': 23.7805759907,
'cool': 27.148763895,
'dimension': 90.4914340973
}
self.totalRunTimeFactor = 0
for v in self.sliceStepTimeFactor.itervalues():
self.totalRunTimeFactor += v
self.sizer = wx.GridBagSizer(2, 2)
self.statusText = wx.StaticText(self, -1, "Building: %s" % (resultFilename))
self.progressGauge = wx.Gauge(self, -1)
@ -690,13 +735,13 @@ class ProjectSliceProgressWindow(wx.Frame):
def SetProgress(self, stepName, layer, maxLayer):
if self.prevStep != stepName:
self.totalDoneFactor += self.sliceStepTimeFactor[self.prevStep]
self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep]
newTime = time.time()
#print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName
self.startTime = newTime
self.prevStep = stepName
progresValue = ((self.totalDoneFactor + self.sliceStepTimeFactor[stepName] * layer / maxLayer) / self.totalRunTimeFactor) * 10000
progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000
self.progressGauge.SetValue(int(progresValue))
self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")

View File

@ -15,27 +15,6 @@ class sliceProgessPanel(wx.Panel):
self.filelist = filelist
self.abort = False
#How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left.
self.sliceStepTimeFactor = {
'start': 3.3713991642,
'slice': 15.4984838963,
'preface': 5.17178297043,
'inset': 116.362634182,
'fill': 215.702672005,
'multiply': 21.9536788464,
'speed': 12.759510994,
'raft': 31.4580039978,
'skirt': 19.3436040878,
'skin': 1.0,
'joris': 1.0,
'comb': 23.7805759907,
'cool': 27.148763895,
'dimension': 90.4914340973
}
self.totalRunTimeFactor = 0
for v in self.sliceStepTimeFactor.itervalues():
self.totalRunTimeFactor += v
box = wx.StaticBox(self, -1, filelist[0])
self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
@ -125,13 +104,13 @@ class sliceProgessPanel(wx.Panel):
def SetProgress(self, stepName, layer, maxLayer):
if self.prevStep != stepName:
self.totalDoneFactor += self.sliceStepTimeFactor[self.prevStep]
self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep]
newTime = time.time()
#print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName
self.startTime = newTime
self.prevStep = stepName
progresValue = ((self.totalDoneFactor + self.sliceStepTimeFactor[stepName] * layer / maxLayer) / self.totalRunTimeFactor) * 10000
progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000
self.progressGauge.SetValue(int(progresValue))
self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")

View File

@ -180,6 +180,7 @@ class NormalButton(buttons.GenBitmapButton):
super(NormalButton, self).__init__(parent, id, self.bitmap, size=size)
self.helpText = helpText
self.callback = callback
self.SetBezelWidth(1)
self.SetUseFocusIndicator(False)
@ -187,10 +188,14 @@ class NormalButton(buttons.GenBitmapButton):
self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
self.Bind(wx.EVT_BUTTON, callback)
self.Bind(wx.EVT_BUTTON, self.OnButton)
parent.AddControl(self)
def OnButton(self, event):
self.GetParent().OnPopupHide(event)
self.callback(event)
def OnMouseEnter(self, event):
self.GetParent().OnPopupDisplay(event)
event.Skip()

View File

@ -11,7 +11,7 @@ SUCCESS = 0
WARNING = 1
ERROR = 2
class validFloat():
class validFloat(object):
def __init__(self, setting, minValue = None, maxValue = None):
self.setting = setting
self.setting.validators.append(self)
@ -29,7 +29,7 @@ class validFloat():
except (ValueError, SyntaxError):
return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid number or expression'
class validInt():
class validInt(object):
def __init__(self, setting, minValue = None, maxValue = None):
self.setting = setting
self.setting.validators.append(self)
@ -47,7 +47,7 @@ class validInt():
except (ValueError, SyntaxError):
return ERROR, '"' + str(self.setting.GetValue()) + '" is not a valid whole number or expression'
class warningAbove():
class warningAbove(object):
def __init__(self, setting, minValueForWarning, warningMessage):
self.setting = setting
self.setting.validators.append(self)
@ -68,7 +68,7 @@ class warningAbove():
#We already have an error by the int/float validator in this case.
return SUCCESS, ''
class wallThicknessValidator():
class wallThicknessValidator(object):
def __init__(self, setting):
self.setting = setting
self.setting.validators.append(self)
@ -94,7 +94,7 @@ class wallThicknessValidator():
#We already have an error by the int/float validator in this case.
return SUCCESS, ''
class printSpeedValidator():
class printSpeedValidator(object):
def __init__(self, setting):
self.setting = setting
self.setting.validators.append(self)

BIN
Cura/images/copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

BIN
Cura/images/move-down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

BIN
Cura/images/move-up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

BIN
Cura/images/object-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

View File

@ -9,13 +9,13 @@ import os
from util import util3d
from util import profile
class gcodePath():
class gcodePath(object):
def __init__(self, newType, pathType, startPoint):
self.type = newType
self.pathType = pathType
self.list = [startPoint]
class gcode():
class gcode(object):
def __init__(self):
self.regMatch = {}
self.layerList = []

View File

@ -5,6 +5,28 @@ import platform, os, subprocess, sys
from cura_sf.skeinforge_application.skeinforge_utilities import skeinforge_craft
from util import profile
#How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left.
sliceStepTimeFactor = {
'start': 3.3713991642,
'slice': 15.4984838963,
'preface': 5.17178297043,
'inset': 116.362634182,
'fill': 215.702672005,
'multiply': 21.9536788464,
'speed': 12.759510994,
'raft': 31.4580039978,
'skirt': 19.3436040878,
'skin': 1.0,
'joris': 1.0,
'comb': 23.7805759907,
'cool': 27.148763895,
'dimension': 90.4914340973
}
totalRunTimeFactor = 0
for v in sliceStepTimeFactor.itervalues():
totalRunTimeFactor += v
def getPyPyExe():
"Return the path to the pypy executable if we can find it. Else return False"
if platform.system() == "Windows":

View File

@ -9,11 +9,11 @@ import struct
from util import util3d
class stlFace():
class stlFace(object):
def __init__(self, v0, v1, v2):
self.v = [v0, v1, v2]
class stlModel():
class stlModel(object):
def __init__(self):
self.faces = []
self.vertexes = []

View File

@ -1,7 +1,7 @@
import math
class Vector3():
class Vector3(object):
def __init__(self, x=0.0, y=0.0, z=0.0):
self.x = x
self.y = y