Merge remote-tracking branch 'upstream/master' into macosx

Conflicts:
	Cura/gui/configWizard.py
	Cura/gui/mainWindow.py
	Cura/gui/opengl.py
	Cura/gui/printWindow.py
	scripts/osx64/Cura.app/Contents/MacOS/Cura
master
Ilya Kulakov 2012-12-06 00:33:55 +07:00
commit 9f3d727817
26 changed files with 1487 additions and 1277 deletions

View File

@ -10,8 +10,9 @@ class Stk500v2(ispBase.IspBase):
self.serial = None
self.seq = 1
self.lastAddr = -1
self.progressCallback = None
def connect(self, port = 'COM31', speed = 115200):
def connect(self, port = 'COM22', speed = 115200):
if self.serial != None:
self.close()
try:
@ -145,8 +146,8 @@ class Stk500v2(ispBase.IspBase):
def main():
programmer = Stk500v2()
programmer.connect()
programmer.programChip(intelHex.readHex("cfg_4f55234def059.hex"))
programmer.connect(port = sys.argv[1])
programmer.programChip(intelHex.readHex(sys.argv[2]))
sys.exit(1)
if __name__ == '__main__':

View File

@ -28,6 +28,8 @@ class daeModel(triangle_mesh.TriangleMesh):
self._geometryList = []
r.ParseFile(open(filename, "r"))
self._scale = float(self._base['collada'][0]['asset'][0]['unit'][0]['_meter']) * 1000
for instance_visual_scene in self._base['collada'][0]['scene'][0]['instance_visual_scene']:
for node in self._idMap[instance_visual_scene['_url']]['node']:
self._ProcessNode2(node)
@ -81,9 +83,9 @@ class daeModel(triangle_mesh.TriangleMesh):
startIndex = len(self.vertexes)
for idx in xrange(0, len(positionList)/3):
x = positionList[idx*3]
y = positionList[idx*3+1]
z = positionList[idx*3+2]
x = positionList[idx*3] * self._scale
y = positionList[idx*3+1] * self._scale
z = positionList[idx*3+2] * self._scale
if matrix != None:
self.vertexes.append(Vector3(x * matrix[0] + y * matrix[1] + z * matrix[2] + matrix[3], x * matrix[4] + y * matrix[5] + z * matrix[6] + matrix[7], x * matrix[8] + y * matrix[9] + z * matrix[10] + matrix[11]))
else:

View File

@ -114,8 +114,8 @@ def getProfileInformation():
'SwapYZ': storedSetting("swap_yz"),
'Scale': storedSettingFloat("model_scale"),
'Rotate': storedSettingFloat("model_rotate_base"),
'CenterX': storedSettingFloat("machine_center_x"),
'CenterY': storedSettingFloat("machine_center_y"),
'CenterX': lambda setting: profile.getProfileSettingFloat('object_center_x') if profile.getProfileSettingFloat('object_center_x') > 0 else profile.getPreferenceFloat("machine_width") / 2,
'CenterY': lambda setting: profile.getProfileSettingFloat('object_center_y') if profile.getProfileSettingFloat('object_center_y') > 0 else profile.getPreferenceFloat("machine_depth") / 2,
'AlternativeCenterFile': storedSetting("alternative_center"),
},'scale': {
'Activate_Scale': "False",
@ -176,8 +176,8 @@ def getProfileInformation():
'Thread_Sequence_Choice': storedSetting('sequence'),
},'multiply': {
'Activate_Multiply': "False",
'Center_X_mm': storedSettingFloat("machine_center_x"),
'Center_Y_mm': storedSettingFloat("machine_center_y"),
'Center_X_mm': lambda setting: profile.getProfileSettingFloat('object_center_x') if profile.getProfileSettingFloat('object_center_x') > 0 else profile.getPreferenceFloat("machine_width") / 2,
'Center_Y_mm': lambda setting: profile.getProfileSettingFloat('object_center_y') if profile.getProfileSettingFloat('object_center_y') > 0 else profile.getPreferenceFloat("machine_depth") / 2,
'Number_of_Columns_integer': storedSetting('model_multiply_x'),
'Number_of_Rows_integer': storedSetting('model_multiply_y'),
'Reverse_Sequence_every_Odd_Layer': DEFSET,
@ -311,8 +311,8 @@ def getProfileInformation():
'Fan_speed_min_%': storedSettingInt('fan_speed'),
'Fan_speed_max_%': storedSettingInt('fan_speed_max'),
},'hop': {
'Activate_Hop': "False",
'Hop_Over_Layer_Thickness_ratio': DEFSET,
'Activate_Hop': storedSetting('hop_on_move'),
'Hop_Over_Layer_Thickness_ratio': lambda setting: 0.2 / profile.getProfileSettingFloat('layer_height'),
'Minimum_Hop_Angle_degrees': DEFSET,
},'wipe': {
'Activate_Wipe': "False",

View File

@ -266,7 +266,7 @@ def writeOutput(fileName, shouldAnalyze=True):
repository = ExportRepository()
settings.getReadRepository(repository)
startTime = time.time()
print('File ' + archive.getSummarizedFileName(fileName) + ' is being chain exported.')
print('File ' + archive.getSummarizedFileName(fileName.encode('ascii', 'replace')) + ' is being chain exported.')
fileNameSuffix = fileName[: fileName.rfind('.')]
if repository.addExportSuffix.value:
fileNameSuffix += '_export'

View File

@ -10,6 +10,7 @@ import wx.wizard
from gui import firmwareInstall
from gui import toolbarUtil
from gui import printWindow
from util import machineCom
from util import profile
from util.resources import getPathForImage
@ -34,28 +35,40 @@ class InfoBox(wx.Panel):
self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
self.text = wx.StaticText(self, -1, '')
self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
self.sizer.AddGrowableCol(1)
self.extraInfoButton.Show(False)
self.extraInfoUrl = ''
self.busyState = None
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
self.timer.Start(100)
def SetInfo(self, info):
self.SetBackgroundColour('#FFFF80')
self.text.SetLabel(info)
self.extraInfoButton.Show(False)
self.Refresh()
def SetError(self, info):
def SetError(self, info, extraInfoUrl):
self.extraInfoUrl = extraInfoUrl
self.SetBackgroundColour('#FF8080')
self.text.SetLabel(info)
self.extraInfoButton.Show(True)
self.Layout()
self.SetErrorIndicator()
self.Refresh()
def SetAttention(self, info):
self.SetBackgroundColour('#FFFF80')
self.text.SetLabel(info)
self.extraInfoButton.Show(False)
self.SetAttentionIndicator()
self.Refresh()
@ -63,6 +76,9 @@ class InfoBox(wx.Panel):
self.busyState = 0
self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
def doExtraInfo(self, e):
webbrowser.open(self.extraInfoUrl)
def doBusyUpdate(self, e):
if self.busyState == None:
return
@ -225,8 +241,6 @@ class RepRapInfoPage(InfoPage):
profile.putPreference('machine_depth', self.machineDepth.GetValue())
profile.putPreference('machine_height', self.machineHeight.GetValue())
profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
profile.putProfileSetting('machine_center_x', profile.getPreferenceFloat('machine_width') / 2)
profile.putProfileSetting('machine_center_y', profile.getPreferenceFloat('machine_depth') / 2)
profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
@ -255,8 +269,6 @@ class MachineSelectPage(InfoPage):
profile.putPreference('machine_height', '200')
profile.putPreference('machine_type', 'ultimaker')
profile.putProfileSetting('nozzle_size', '0.4')
profile.putProfileSetting('machine_center_x', '100')
profile.putProfileSetting('machine_center_y', '100')
else:
profile.putPreference('machine_width', '80')
profile.putPreference('machine_depth', '80')
@ -264,11 +276,31 @@ class MachineSelectPage(InfoPage):
profile.putPreference('machine_type', 'reprap')
profile.putPreference('startMode', 'Normal')
profile.putProfileSetting('nozzle_size', '0.5')
profile.putProfileSetting('machine_center_x', '40')
profile.putProfileSetting('machine_center_y', '40')
profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
class SelectParts(InfoPage):
def __init__(self, parent):
super(SelectParts, self).__init__(parent, "Select upgraded parts you have")
self.AddText('To assist you in having better default settings for your Ultimaker\nCura would like to know which upgrades you have in your machine.')
self.AddSeperator()
self.springExtruder = self.AddCheckbox('Extruder drive upgrade')
self.heatedBed = self.AddCheckbox('Heated printer bed (self build)')
self.dualExtrusion = self.AddCheckbox('Dual extrusion (experimental)')
self.AddSeperator()
self.AddText('If you have an Ultimaker bought after october 2012 you will have the\nExtruder drive upgrade. If you do not have this upgrade,\nit is highly recommended to improve reliablity.')
self.AddText('This upgrade can be bought from the Ultimaker webshop shop\nor found on thingiverse as thing:26094')
self.springExtruder.SetValue(True)
def StoreData(self):
profile.putPreference('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
if self.dualExtrusion.GetValue():
profile.putPreference('extruder_amount', '2')
if getPreference('ultimaker_extruder_upgrade') == 'True':
putProfileSetting('retraction_enable', 'True')
class FirmwareUpgradePage(InfoPage):
def __init__(self, parent):
super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
@ -332,6 +364,8 @@ class UltimakerCheckupPage(InfoPage):
self.infoBox = self.AddInfoBox()
self.machineState = self.AddText('')
self.temperatureLabel = self.AddText('')
self.errorLogButton = self.AddButton('Show error log')
self.errorLogButton.Show(False)
self.AddSeperator()
self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
self.comm = None
@ -342,6 +376,8 @@ class UltimakerCheckupPage(InfoPage):
self.zMinStop = False
self.zMaxStop = False
self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
def __del__(self):
if self.comm != None:
self.comm.close()
@ -354,6 +390,7 @@ class UltimakerCheckupPage(InfoPage):
self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
def OnCheckClick(self, e=None):
self.errorLogButton.Show(False)
if self.comm != None:
self.comm.close()
del self.comm
@ -368,6 +405,9 @@ class UltimakerCheckupPage(InfoPage):
self.checkupState = 0
self.comm = machineCom.MachineCom(callbackObject=self)
def OnErrorLog(self, e):
printWindow.LogWindow('\n'.join(self.comm.getLog()))
def mcLog(self, message):
pass
@ -410,7 +450,7 @@ class UltimakerCheckupPage(InfoPage):
if self.tempCheckTimeout < 1:
self.checkupState = -1
wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!')
wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura/Temperature_measurement_problems')
self.comm.sendCommand('M104 S0')
self.comm.sendCommand('M104 S0')
wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
@ -420,10 +460,15 @@ class UltimakerCheckupPage(InfoPage):
return
if self.comm.isOperational():
wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
elif self.comm.isError():
wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.')
wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura/Connection_problems')
wx.CallAfter(self.endstopBitmap.Show, False)
wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
wx.CallAfter(self.errorLogButton.Show, True)
wx.CallAfter(self.Layout)
else:
wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
def mcMessage(self, message):
@ -638,6 +683,7 @@ class configWizard(wx.wizard.Wizard):
self.firstInfoPage = FirstInfoPage(self)
self.machineSelectPage = MachineSelectPage(self)
self.ultimakerSelectParts = SelectParts(self)
self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
self.ultimakerCheckupPage = UltimakerCheckupPage(self)
self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
@ -645,7 +691,8 @@ class configWizard(wx.wizard.Wizard):
self.repRapInfoPage = RepRapInfoPage(self)
wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)
wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
#wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
#wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)

View File

@ -67,6 +67,9 @@ class expertConfigWindow(configBase.configWindowBase):
configBase.TitleRow(right, "Retraction")
c = configBase.SettingRow(right, "Retract on jumps only", 'retract_on_jumps_only', True, 'Only retract when we are making a move that is over a hole in the model, else retract on every move. This effects print quality in different ways.')
configBase.TitleRow(right, "Hop")
c = configBase.SettingRow(right, "Enable hop on move", 'hop_on_move', False, 'When moving from print position to print position, raise the printer head 0.2mm so it does not knock off the print (experimental).')
main.Fit()
self.Fit()

View File

@ -84,7 +84,7 @@ class flatSlicerWindow(wx.Frame):
if dlg.ShowModal() == wx.ID_OK:
self.filename = dlg.GetPath()
self.svg = svg.SVG(self.filename)
self.svg.center(complex(profile.getProfileSettingFloat('machine_center_x'), profile.getProfileSettingFloat('machine_center_y')))
self.svg.center(complex(profile.getPreferenceFloat('machine_width')/2, profile.getPreferenceFloat('machine_depth')/2))
self.preview.Refresh()
dlg.Destroy()

View File

@ -113,7 +113,7 @@ class mainWindow(configBase.configWindowBase):
helpMenu = wx.Menu()
i = helpMenu.Append(-1, 'Online documentation...')
self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://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')
@ -134,7 +134,7 @@ class mainWindow(configBase.configWindowBase):
(left, right) = self.CreateConfigTab(nb, 'Print config')
configBase.TitleRow(left, "Accuracy")
configBase.TitleRow(left, "Quality")
c = configBase.SettingRow(left, "Layer height (mm)", 'layer_height', '0.2', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.')
validators.validFloat(c, 0.0001)
validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 80.0 / 100.0), "Thicker layers then %.2fmm (80%% nozzle size) usually give bad results and are not recommended.")
@ -149,12 +149,6 @@ class mainWindow(configBase.configWindowBase):
c = configBase.SettingRow(left, "Fill Density (%)", 'fill_density', '20', 'This controls how densily filled the insides of your print will be. For a solid part use 100%, for an empty part use 0%. A value around 20% is usually enough')
validators.validFloat(c, 0.0, 100.0)
configBase.TitleRow(left, "Skirt")
c = configBase.SettingRow(left, "Line count", 'skirt_line_count', '1', 'The skirt is a line drawn around the object at the first layer. This helps to prime your extruder, and to see if the object fits on your platform.\nSetting this to 0 will disable the skirt. Multiple skirt lines can help priming your extruder better for small objects.')
validators.validInt(c, 0, 10)
c = configBase.SettingRow(left, "Start distance (mm)", 'skirt_gap', '6.0', 'The distance between the skirt and the first layer.\nThis is the minimal distance, multiple skirt lines will be put outwards from this distance.')
validators.validFloat(c, 0.0)
configBase.TitleRow(right, "Speed && Temperature")
c = configBase.SettingRow(right, "Print speed (mm/s)", 'print_speed', '50', 'Speed at which printing happens. A well adjusted Ultimaker can reach 150mm/s, but for good quality prints you want to print slower. Printing speed depends on a lot of factors. So you will be experimenting with optimal settings for this.')
validators.validFloat(c, 1.0)
@ -187,15 +181,15 @@ class mainWindow(configBase.configWindowBase):
configBase.TitleRow(left, "Machine size")
c = configBase.SettingRow(left, "Nozzle size (mm)", 'nozzle_size', '0.4', 'The nozzle size is very important, this is used to calculate the line width of the infill, and used to calculate the amount of outside wall lines and thickness for the wall thickness you entered in the print settings.')
validators.validFloat(c, 0.1, 10.0)
c = configBase.SettingRow(left, "Machine center X (mm)", 'machine_center_x', '100', 'The center of your machine, your print will be placed at this location')
validators.validInt(c, 10)
configBase.settingNotify(c, self.preview3d.updateCenterX)
c = configBase.SettingRow(left, "Machine center Y (mm)", 'machine_center_y', '100', 'The center of your machine, your print will be placed at this location')
validators.validInt(c, 10)
configBase.settingNotify(c, self.preview3d.updateCenterY)
configBase.TitleRow(left, "Skirt")
c = configBase.SettingRow(left, "Line count", 'skirt_line_count', '1', 'The skirt is a line drawn around the object at the first layer. This helps to prime your extruder, and to see if the object fits on your platform.\nSetting this to 0 will disable the skirt. Multiple skirt lines can help priming your extruder better for small objects.')
validators.validInt(c, 0, 10)
c = configBase.SettingRow(left, "Start distance (mm)", 'skirt_gap', '6.0', 'The distance between the skirt and the first layer.\nThis is the minimal distance, multiple skirt lines will be put outwards from this distance.')
validators.validFloat(c, 0.0)
configBase.TitleRow(left, "Retraction")
c = configBase.SettingRow(left, "Minimal travel (mm)", 'retraction_min_travel', '5.0', 'Minimal amount of travel needed for a retraction to happen at all. To make sure you do not get a lot of retractions in a small area')
c = configBase.SettingRow(left, "Minimum travel (mm)", 'retraction_min_travel', '5.0', 'Minimum amount of travel needed for a retraction to happen at all. To make sure you do not get a lot of retractions in a small area')
validators.validFloat(c, 0.0)
c = configBase.SettingRow(left, "Speed (mm/s)", 'retraction_speed', '40.0', 'Speed at which the filament is retracted, a higher retraction speed works better. But a very high retraction speed can lead to filament grinding.')
validators.validFloat(c, 0.1)
@ -218,11 +212,11 @@ class mainWindow(configBase.configWindowBase):
validators.validFloat(c, 0.0)
c = configBase.SettingRow(right, "Enable cooling fan", 'fan_enabled', True, 'Enable the cooling fan during the print. The extra cooling from the cooling fan is essensial during faster prints.')
configBase.TitleRow(right, "Accuracy")
configBase.TitleRow(right, "Quality")
c = configBase.SettingRow(right, "Initial layer thickness (mm)", 'bottom_thickness', '0.0', 'Layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier. Set to 0.0 to have the bottom layer thickness the same as the other layers.')
validators.validFloat(c, 0.0)
validators.warningAbove(c, lambda : (float(profile.getProfileSetting('nozzle_size')) * 3.0 / 4.0), "A bottom layer of more then %.2fmm (3/4 nozzle size) usually give bad results and is not recommended.")
c = configBase.SettingRow(right, "Enable 'skin'", 'enable_skin', False, 'Skin prints the outer lines of the prints twice, each time with half the thickness. This gives the illusion of a higher print quality.')
c = configBase.SettingRow(right, "Duplicate outlines", 'enable_skin', False, 'Skin prints the outer lines of the prints twice, each time with half the thickness. This gives the illusion of a higher print quality.')
#Plugin page
self.pluginPanel = pluginPanel.pluginPanel(nb)
@ -236,7 +230,7 @@ class mainWindow(configBase.configWindowBase):
nb.AddPage(self.alterationPanel, "Start/End-GCode")
# load and slice buttons.
loadButton = wx.Button(self, -1, '&Load Model')
loadButton = wx.Button(self, -1, '&Load model')
sliceButton = wx.Button(self, -1, 'P&repare print')
printButton = wx.Button(self, -1, '&Print')
self.Bind(wx.EVT_BUTTON, lambda e: self._showModelLoadDialog(1), loadButton)
@ -331,10 +325,6 @@ class mainWindow(configBase.configWindowBase):
dlg.Destroy()
if result:
profile.resetGlobalProfile()
if profile.getPreference('machine_type') == 'reprap':
profile.putProfileSetting('nozzle_size', '0.5')
profile.putProfileSetting('machine_center_x', '40')
profile.putProfileSetting('machine_center_y', '40')
self.updateProfileToControls()
def OnBatchRun(self, e):

View File

@ -357,6 +357,44 @@ def DrawMesh(mesh):
glDisableClientState(GL_NORMAL_ARRAY);
def DrawMeshSteep(mesh, angle):
cosAngle = math.sin(angle / 180.0 * math.pi)
glDisable(GL_LIGHTING)
glDepthFunc(GL_EQUAL)
for i in xrange(0, int(mesh.vertexCount), 3):
if mesh.normal[i][2] < -0.999999:
if mesh.vertexes[i + 0][2] > 0.01:
glColor3f(0.5, 0, 0)
glBegin(GL_TRIANGLES)
glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
glEnd()
elif mesh.normal[i][2] < -cosAngle:
glColor3f(-mesh.normal[i][2], 0, 0)
glBegin(GL_TRIANGLES)
glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
glEnd()
elif mesh.normal[i][2] > 0.999999:
if mesh.vertexes[i + 0][2] > 0.01:
glColor3f(0.5, 0, 0)
glBegin(GL_TRIANGLES)
glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
glEnd()
elif mesh.normal[i][2] > cosAngle:
glColor3f(mesh.normal[i][2], 0, 0)
glBegin(GL_TRIANGLES)
glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
glEnd()
glDepthFunc(GL_LESS)
def DrawGCodeLayer(layer):
filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
filamentArea = math.pi * filamentRadius * filamentRadius

View File

@ -3,6 +3,7 @@ import sys, math, threading, os, webbrowser
from wx.lib import scrolledpanel
from util import profile
from util import exporer
class pluginPanel(wx.Panel):
def __init__(self, parent):
@ -20,19 +21,23 @@ class pluginPanel(wx.Panel):
self.listbox = wx.ListBox(self, -1, choices=effectStringList)
title = wx.StaticText(self, -1, "Plugins:")
title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
helpButton = wx.Button(self, -1, '?', style=wx.BU_EXACTFIT)
addButton = wx.Button(self, -1, '>', style=wx.BU_EXACTFIT)
openPluginLocationButton = wx.Button(self, -1, 'Open plugin location')
sb = wx.StaticBox(self, label="Enabled plugins")
boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
self.pluginEnabledPanel = scrolledpanel.ScrolledPanel(self)
self.pluginEnabledPanel.SetupScrolling(False, True)
sizer.Add(title, (0,0), border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.TOP)
sizer.Add(self.listbox, (1,0), span=(2,1), border=10, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM)
sizer.Add(addButton, (1,1), border=5, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_BOTTOM)
sizer.Add(boxsizer, (1,2), span=(2,1), border=10, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM)
sizer.Add(helpButton, (0,1), border=10, flag=wx.ALIGN_RIGHT|wx.RIGHT|wx.TOP)
sizer.Add(self.listbox, (1,0), span=(2,2), border=10, flag=wx.EXPAND|wx.LEFT|wx.RIGHT)
sizer.Add(addButton, (1,2), border=5, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_BOTTOM)
sizer.Add(boxsizer, (1,3), span=(2,1), border=10, flag=wx.EXPAND|wx.LEFT|wx.RIGHT)
sizer.Add(openPluginLocationButton, (3, 0), span=(1,2), border=10, flag=wx.LEFT|wx.BOTTOM)
boxsizer.Add(self.pluginEnabledPanel, 1, flag=wx.EXPAND)
sizer.AddGrowableCol(2)
sizer.AddGrowableCol(3)
sizer.AddGrowableRow(1)
sizer.AddGrowableRow(2)
@ -40,6 +45,9 @@ class pluginPanel(wx.Panel):
self.pluginEnabledPanel.SetSizer(sizer)
self.Bind(wx.EVT_BUTTON, self.OnAdd, addButton)
self.Bind(wx.EVT_BUTTON, self.OnGeneralHelp, helpButton)
self.Bind(wx.EVT_BUTTON, self.OnOpenPluginLocation, openPluginLocationButton)
self.listbox.Bind(wx.EVT_LEFT_DCLICK, self.OnAdd)
self.panelList = []
self.updateProfileToControls()
@ -151,3 +159,9 @@ class pluginPanel(wx.Panel):
fname = fname[0].upper() + fname[1:]
fname = fname[:fname.rfind('.')]
webbrowser.open('http://wiki.ultimaker.com/CuraPlugin:_' + fname)
def OnGeneralHelp(self, e):
webbrowser.open('http://wiki.ultimaker.com/Category:CuraPlugin')
def OnOpenPluginLocation(self, e):
exporer.openExporerPath(profile.getPluginBasePaths()[0])

View File

@ -22,11 +22,11 @@ class preferencesDialog(configBase.configWindowBase):
configBase.TitleRow(left, 'Machine settings')
c = configBase.SettingRow(left, 'Steps per E', 'steps_per_e', '0', 'Amount of steps per mm filament extrusion', type = 'preference')
validators.validFloat(c, 0.1)
c = configBase.SettingRow(left, 'Machine width (mm)', 'machine_width', '205', 'Size of the machine in mm', type = 'preference')
c = configBase.SettingRow(left, 'Maximum width (mm)', 'machine_width', '205', 'Size of the machine in mm', type = 'preference')
validators.validFloat(c, 10.0)
c = configBase.SettingRow(left, 'Machine depth (mm)', 'machine_depth', '205', 'Size of the machine in mm', type = 'preference')
c = configBase.SettingRow(left, 'Maximum depth (mm)', 'machine_depth', '205', 'Size of the machine in mm', type = 'preference')
validators.validFloat(c, 10.0)
c = configBase.SettingRow(left, 'Machine height (mm)', 'machine_height', '200', 'Size of the machine in mm', type = 'preference')
c = configBase.SettingRow(left, 'Maximum height (mm)', 'machine_height', '200', 'Size of the machine in mm', type = 'preference')
validators.validFloat(c, 10.0)
c = configBase.SettingRow(left, 'Extruder count', 'extruder_amount', ['1', '2', '3', '4'], 'Amount of extruders in your machine.', type = 'preference')
c = configBase.SettingRow(left, 'Heated bed', 'has_heated_bed', False, 'If you have an heated bed, this enabled heated bed settings', type = 'preference')
@ -44,11 +44,11 @@ class preferencesDialog(configBase.configWindowBase):
c = configBase.SettingRow(left, 'Model colour (%d)' % (i+1), 'model_colour%d' % (i+1), wx.Colour(0,0,0), '', type = 'preference')
configBase.TitleRow(right, 'Filament settings')
c = configBase.SettingRow(right, 'Filament density (kg/m3)', 'filament_density', '1300', 'Weight of the filament per m3. Around 1300 for PLA. And around 1040 for ABS. This value is used to estimate the weight if the filament used for the print.', type = 'preference')
c = configBase.SettingRow(right, 'Density (kg/m3)', 'filament_density', '1300', 'Weight of the filament per m3. Around 1300 for PLA. And around 1040 for ABS. This value is used to estimate the weight if the filament used for the print.', type = 'preference')
validators.validFloat(c, 500.0, 3000.0)
c = configBase.SettingRow(right, 'Filament cost (price/kg)', 'filament_cost_kg', '0', 'Cost of your filament per kg, to estimate the cost of the final print.', type = 'preference')
c = configBase.SettingRow(right, 'Cost (price/kg)', 'filament_cost_kg', '0', 'Cost of your filament per kg, to estimate the cost of the final print.', type = 'preference')
validators.validFloat(c, 0.0)
c = configBase.SettingRow(right, 'Filament cost (price/m)', 'filament_cost_meter', '0', 'Cost of your filament per meter, to estimate the cost of the final print.', type = 'preference')
c = configBase.SettingRow(right, 'Cost (price/m)', 'filament_cost_meter', '0', 'Cost of your filament per meter, to estimate the cost of the final print.', type = 'preference')
validators.validFloat(c, 0.0)
configBase.TitleRow(right, 'Communication settings')

View File

@ -43,9 +43,10 @@ class previewPanel(wx.Panel):
self.gcode = None
self.objectsMinV = None
self.objectsMaxV = None
self.objectsBounderyCircleSize = None
self.loadThread = None
self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height'))
self.machineCenter = util3d.Vector3(float(profile.getProfileSetting('machine_center_x')), float(profile.getProfileSetting('machine_center_y')), 0)
self.machineCenter = util3d.Vector3(self.machineSize.x / 2, self.machineSize.y / 2, 0)
self.glCanvas = PreviewGLCanvas(self)
#Create the popup window
@ -77,6 +78,7 @@ class previewPanel(wx.Panel):
self.toolbar.AddSeparator()
self.showBorderButton = toolbarUtil.ToggleButton(self.toolbar, '', 'view-border-on.png', 'view-border-off.png', 'Show model borders', callback=self.OnViewChange)
self.showSteepOverhang = toolbarUtil.ToggleButton(self.toolbar, '', 'steepOverhang-on.png', 'steepOverhang-off.png', 'Show steep overhang', callback=self.OnViewChange)
self.toolbar.AddSeparator()
group = []
@ -90,18 +92,21 @@ class previewPanel(wx.Panel):
self.layerSpin = wx.SpinCtrl(self.toolbar, -1, '', size=(21*4,21), style=wx.SP_ARROW_KEYS)
self.toolbar.AddControl(self.layerSpin)
self.Bind(wx.EVT_SPINCTRL, self.OnLayerNrChange, self.layerSpin)
self.toolbar.AddSeparator()
self.toolbarInfo = wx.TextCtrl(self.toolbar, -1, '', style=wx.TE_READONLY)
self.toolbar.AddControl(self.toolbarInfo)
self.toolbar2 = toolbarUtil.Toolbar(self)
# Mirror
self.mirrorX = toolbarUtil.ToggleButton(self.toolbar2, 'flip_x', 'object-mirror-x-on.png', 'object-mirror-x-off.png', 'Mirror X', callback=self.updateModelTransform)
self.mirrorY = toolbarUtil.ToggleButton(self.toolbar2, 'flip_y', 'object-mirror-y-on.png', 'object-mirror-y-off.png', 'Mirror Y', callback=self.updateModelTransform)
self.mirrorZ = toolbarUtil.ToggleButton(self.toolbar2, 'flip_z', 'object-mirror-z-on.png', 'object-mirror-z-off.png', 'Mirror Z', callback=self.updateModelTransform)
self.mirrorX = toolbarUtil.ToggleButton(self.toolbar2, 'flip_x', 'object-mirror-x-on.png', 'object-mirror-x-off.png', 'Mirror X', callback=self.returnToModelViewAndUpdateModel)
self.mirrorY = toolbarUtil.ToggleButton(self.toolbar2, 'flip_y', 'object-mirror-y-on.png', 'object-mirror-y-off.png', 'Mirror Y', callback=self.returnToModelViewAndUpdateModel)
self.mirrorZ = toolbarUtil.ToggleButton(self.toolbar2, 'flip_z', 'object-mirror-z-on.png', 'object-mirror-z-off.png', 'Mirror Z', callback=self.returnToModelViewAndUpdateModel)
self.toolbar2.AddSeparator()
# Swap
self.swapXZ = toolbarUtil.ToggleButton(self.toolbar2, 'swap_xz', 'object-swap-xz-on.png', 'object-swap-xz-off.png', 'Swap XZ', callback=self.updateModelTransform)
self.swapYZ = toolbarUtil.ToggleButton(self.toolbar2, 'swap_yz', 'object-swap-yz-on.png', 'object-swap-yz-off.png', 'Swap YZ', callback=self.updateModelTransform)
self.swapXZ = toolbarUtil.ToggleButton(self.toolbar2, 'swap_xz', 'object-swap-xz-on.png', 'object-swap-xz-off.png', 'Swap XZ', callback=self.returnToModelViewAndUpdateModel)
self.swapYZ = toolbarUtil.ToggleButton(self.toolbar2, 'swap_yz', 'object-swap-yz-on.png', 'object-swap-yz-off.png', 'Swap YZ', callback=self.returnToModelViewAndUpdateModel)
self.toolbar2.AddSeparator()
# Scale
@ -136,6 +141,11 @@ class previewPanel(wx.Panel):
sizer.Add(self.toolbar2, 0, flag=wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, border=1)
self.SetSizer(sizer)
def returnToModelViewAndUpdateModel(self):
if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed':
self.setViewMode('Normal')
self.updateModelTransform()
def OnMove(self, e = None):
if e != None:
e.Skip()
@ -168,21 +178,34 @@ class previewPanel(wx.Panel):
if self.scale.GetValue() != '':
scale = self.scale.GetValue()
profile.putProfileSetting('model_scale', scale)
if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed':
self.setViewMode('Normal')
self.glCanvas.Refresh()
def OnScaleMax(self, e):
if self.objectsMaxV != None:
size = (self.objectsMaxV - self.objectsMinV) * float(scale)
self.toolbarInfo.SetValue('%0.1f %0.1f %0.1f' % (size[0], size[1], size[2]))
def OnScaleMax(self, e = None, onlyScaleDown = False):
if self.objectsMinV == None:
return
vMin = self.objectsMinV
vMax = self.objectsMaxV
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax[0] - vMin[0]) / 2)
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
scaleX2 = (self.machineCenter.x) / ((vMax[0] - vMin[0]) / 2)
scaleY2 = (self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
skirtSize = 3
if profile.getProfileSettingFloat('skirt_line_count') > 0:
skirtSize = 3 + profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
scaleX1 = (self.machineSize.x - self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2)
scaleY1 = (self.machineSize.y - self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2)
scaleX2 = (self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2)
scaleY2 = (self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2)
scaleZ = self.machineSize.z / (vMax[2] - vMin[2])
scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
if scale > 1.0 and onlyScaleDown:
return
self.scale.SetValue(str(scale))
profile.putProfileSetting('model_scale', self.scale.GetValue())
if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed':
self.setViewMode('Normal')
self.glCanvas.Refresh()
def OnRotateReset(self, e):
@ -191,7 +214,7 @@ class previewPanel(wx.Panel):
def OnRotate(self, e):
profile.putProfileSetting('model_rotate_base', self.rotate.GetValue())
self.updateModelTransform()
self.returnToModelViewAndUpdateModel()
def On3DClick(self):
self.glCanvas.yaw = 30
@ -210,14 +233,6 @@ class previewPanel(wx.Panel):
def OnLayerNrChange(self, e):
self.glCanvas.Refresh()
def updateCenterX(self):
self.machineCenter.x = profile.getProfileSettingFloat('machine_center_x')
self.glCanvas.Refresh()
def updateCenterY(self):
self.machineCenter.y = profile.getProfileSettingFloat('machine_center_y')
self.glCanvas.Refresh()
def setViewMode(self, mode):
if mode == "Normal":
self.normalViewButton.SetValue(True)
@ -249,8 +264,8 @@ class previewPanel(wx.Panel):
self.loadThread.start()
if showWarning:
if profile.getProfileSettingFloat('model_scale') != 1.0 or profile.getProfileSettingFloat('model_rotate_base') != 0 or profile.getProfileSetting('flip_x') != 'False' or profile.getProfileSetting('flip_y') != 'False' or profile.getProfileSetting('flip_z') != 'False' or profile.getProfileSetting('swap_xz') != 'False' or profile.getProfileSetting('swap_yz') != 'False':
self.ShowWarningPopup('Reset scale, rotation and mirror?', self.OnResetAll)
if profile.getProfileSettingFloat('model_scale') != 1.0 or profile.getProfileSettingFloat('model_rotate_base') != 0 or profile.getProfileSetting('flip_x') != 'False' or profile.getProfileSetting('flip_y') != 'False' or profile.getProfileSetting('flip_z') != 'False' or profile.getProfileSetting('swap_xz') != 'False' or profile.getProfileSetting('swap_yz') != 'False' or len(profile.getPluginConfig()) > 0:
self.ShowWarningPopup('Reset scale, rotation, mirror and plugins?', self.OnResetAll)
def loadReModelFiles(self, filelist):
#Only load this again if the filename matches the file we have already loaded (for auto loading GCode after slicing)
@ -268,10 +283,10 @@ class previewPanel(wx.Panel):
obj.dirty = False
obj.mesh = mesh
self.updateModelTransform()
self.OnScaleMax(None, True)
scale = profile.getProfileSettingFloat('model_scale')
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.toolbarInfo.SetValue('%0.1f %0.1f %0.1f' % (size[0], size[1], size[2]))
self.glCanvas.zoom = numpy.max(size) * 2.5
self.errorList = []
wx.CallAfter(self.updateToolbar)
@ -311,7 +326,8 @@ class previewPanel(wx.Panel):
profile.putProfileSetting('flip_z', 'False')
profile.putProfileSetting('swap_xz', 'False')
profile.putProfileSetting('swap_yz', 'False')
self.updateProfileToControls()
profile.setPluginConfig([])
self.GetParent().updateProfileToControls()
def ShowWarningPopup(self, text, callback = None):
self.warningPopup.text.SetLabel(text)
@ -358,6 +374,7 @@ class previewPanel(wx.Panel):
elif self.mixedViewButton.GetValue():
self.glCanvas.viewMode = "Mixed"
self.glCanvas.drawBorders = self.showBorderButton.GetValue()
self.glCanvas.drawSteepOverhang = self.showSteepOverhang.GetValue()
self.updateToolbar()
self.glCanvas.Refresh()
@ -379,6 +396,7 @@ class previewPanel(wx.Panel):
minV = self.objectList[0].mesh.getMinimum()
maxV = self.objectList[0].mesh.getMaximum()
objectsBounderyCircleSize = self.objectList[0].mesh.bounderyCircleSize
for obj in self.objectList:
if obj.mesh == None:
continue
@ -386,9 +404,11 @@ class previewPanel(wx.Panel):
obj.mesh.getMinimumZ()
minV = numpy.minimum(minV, obj.mesh.getMinimum())
maxV = numpy.maximum(maxV, obj.mesh.getMaximum())
objectsBounderyCircleSize = max(objectsBounderyCircleSize, obj.mesh.bounderyCircleSize)
self.objectsMaxV = maxV
self.objectsMinV = minV
self.objectsBounderyCircleSize = objectsBounderyCircleSize
for obj in self.objectList:
if obj.mesh == None:
continue
@ -400,6 +420,11 @@ class previewPanel(wx.Panel):
# v[1] -= minV[1] + (maxV[1] - minV[1]) / 2
obj.mesh.getMinimumZ()
obj.dirty = True
scale = profile.getProfileSettingFloat('model_scale')
size = (self.objectsMaxV - self.objectsMinV) * scale
self.toolbarInfo.SetValue('%0.1f %0.1f %0.1f' % (size[0], size[1], size[2]))
self.glCanvas.Refresh()
def updateProfileToControls(self):
@ -447,16 +472,15 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
def OnMouseMotion(self,e):
cursorXY = 100000
sizeXY = 0
radius = 0
if self.parent.objectsMaxV != None:
size = (self.parent.objectsMaxV - self.parent.objectsMinV)
sizeXY = math.sqrt((size[0] * size[0]) + (size[1] * size[1]))
radius = self.parent.objectsBounderyCircleSize * profile.getProfileSettingFloat('model_scale')
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 and False:
if cursorXY >= radius * 1.1 and cursorXY <= radius * 1.3:
self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
else:
self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
@ -464,7 +488,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
if e.Dragging() and e.LeftIsDown():
if self.dragType == '':
#Define the drag type depending on the cursor position.
if cursorXY >= sizeXY * 0.7 and cursorXY <= sizeXY * 0.7 + 3 and False:
if cursorXY >= radius * 1.1 and cursorXY <= radius * 1.3:
self.dragType = 'modelRotate'
self.dragStart = math.atan2(cursorZ0[0], cursorZ0[1])
else:
@ -485,6 +509,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
angle = math.atan2(cursorZ0[0], cursorZ0[1])
diff = self.dragStart - angle
self.tempRotate = diff * 180 / math.pi
rot = profile.getProfileSettingFloat('model_rotate_base')
self.tempRotate = round((self.tempRotate + rot) / 15) * 15 - rot
#Workaround for buggy ATI cards.
size = self.GetSizeTuple()
self.SetSize((size[0]+1, size[1]))
@ -492,7 +518,13 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
self.Refresh()
else:
if self.tempRotate != 0:
profile.putProfileSetting('model_rotate_base', profile.getProfileSettingFloat('model_rotate_base') + self.tempRotate)
newRotation = profile.getProfileSettingFloat('model_rotate_base') + self.tempRotate
while newRotation >= 360:
newRotation -= 360
while newRotation < 0:
newRotation += 360
profile.putProfileSetting('model_rotate_base', newRotation)
self.parent.rotate.SetValue(newRotation)
self.parent.updateModelTransform()
self.tempRotate = 0
@ -580,12 +612,16 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
if obj.mesh == None:
continue
if obj.displayList == None:
obj.displayList = glGenLists(1);
obj.displayList = glGenLists(1)
obj.steepDisplayList = glGenLists(1)
if obj.dirty:
obj.dirty = False
glNewList(obj.displayList, GL_COMPILE)
opengl.DrawMesh(obj.mesh)
glEndList()
glNewList(obj.steepDisplayList, GL_COMPILE)
opengl.DrawMeshSteep(obj.mesh, 60)
glEndList()
if self.viewMode == "Mixed":
glDisable(GL_BLEND)
@ -707,6 +743,15 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
opengl.DrawMeshOutline(obj.mesh)
glPopMatrix()
if self.drawSteepOverhang:
glDisable(GL_LIGHTING)
glColor3f(1,1,1)
glPushMatrix()
modelScale = profile.getProfileSettingFloat('model_scale')
glScalef(modelScale, modelScale, modelScale)
glCallList(obj.steepDisplayList)
glPopMatrix()
glPopMatrix()
if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray":
glDisable(GL_LIGHTING)
@ -720,30 +765,37 @@ 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
if self.parent.objectsMaxV != None and False:
if self.parent.objectsMaxV != None:
glDisable(GL_LIGHTING)
glDisable(GL_CULL_FACE)
glEnable(GL_BLEND)
glRotate(self.tempRotate + profile.getProfileSettingFloat('model_rotate_base'), 0, 0, 1)
radius = self.parent.objectsBounderyCircleSize * profile.getProfileSettingFloat('model_scale')
glScalef(radius, radius, 1)
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)
glColor4ub(255,int(f*255/(64/2)),0,255)
glVertex3f(1.1 * math.cos(i/32.0*math.pi), 1.1 * math.sin(i/32.0*math.pi),0.1)
glColor4ub( 0,128,0,255)
glVertex3f(1.3 * math.cos(i/32.0*math.pi), 1.3 * math.sin(i/32.0*math.pi),0.1)
glEnd()
glBegin(GL_TRIANGLES)
glColor4ub(0,0,0,192)
glVertex3f(1, 0.1,0.15)
glVertex3f(1,-0.1,0.15)
glVertex3f(1.4,0,0.15)
glEnd()
glEnable(GL_CULL_FACE)
glPopMatrix()
opengl.DrawMachine(machineSize)
glFlush()
def drawModel(self, obj):

View File

@ -134,7 +134,7 @@ class printWindow(wx.Frame):
self.powerWarningText = wx.StaticText(parent=self.panel,
id=-1,
label="Connect your computer to AC power\nIf it shuts down during printing, the product will be lost.",
label="Your computer is running on battery power.\nConnect your computer to AC power or your print might not finish.",
style=wx.ALIGN_CENTER)
self.powerWarningText.SetBackgroundColour('red')
self.powerWarningText.SetForegroundColour('white')
@ -309,7 +309,7 @@ class printWindow(wx.Frame):
self.camPreview.timer.Start(500)
self.camPreview.Bind(wx.EVT_ERASE_BACKGROUND, self.OnCameraEraseBackground)
self.sizer.AddGrowableRow(5)
self.sizer.AddGrowableRow(6)
self.sizer.AddGrowableCol(3)
self.Bind(wx.EVT_CLOSE, self.OnClose)
@ -521,9 +521,11 @@ class printWindow(wx.Frame):
type = self.powerManagement.get_providing_power_source_type()
if type == power.POWER_TYPE_AC and self.powerWarningText.IsShown():
self.powerWarningText.Hide()
self.panel.Layout()
self.Layout()
elif type != power.POWER_TYPE_AC and not self.powerWarningText.IsShown():
self.powerWarningText.Show()
self.panel.Layout()
self.Layout()
def LoadGCodeFile(self, filename):
@ -579,10 +581,11 @@ class printWindow(wx.Frame):
def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
self.temperatureGraph.addPoint(temp, targetTemp, bedTemp, bedTargetTemp)
if self.temperatureSelect.GetValue() != targetTemp:
wx.CallAfter(self.temperatureSelect.SetValue, targetTemp)
if self.bedTemperatureSelect.GetValue() != bedTargetTemp:
wx.CallAfter(self.bedTemperatureSelect.SetValue, bedTargetTemp)
# ToFix, this causes problems with setting the temperature with the keyboard
# if self.temperatureSelect.GetValue() != targetTemp:
# wx.CallAfter(self.temperatureSelect.SetValue, targetTemp)
# if self.bedTemperatureSelect.GetValue() != bedTargetTemp:
# wx.CallAfter(self.bedTemperatureSelect.SetValue, bedTargetTemp)
def mcStateChange(self, state):
if self.machineCom != None:
@ -643,6 +646,7 @@ class temperatureGraph(wx.Panel):
dc = wx.MemoryDC()
dc.SelectObject(self.backBuffer)
dc.Clear()
dc.SetFont(wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT))
w, h = self.GetSizeTuple()
bgLinePen = wx.Pen('#A0A0A0')
tempPen = wx.Pen('#FF4040')
@ -677,9 +681,12 @@ class temperatureGraph(wx.Panel):
for x in xrange(w, 0, -30):
dc.SetPen(bgLinePen)
dc.DrawLine(x, 0, x, h)
tmpNr = 0
for y in xrange(h - 1, 0, -h * 50 / 300):
dc.SetPen(bgLinePen)
dc.DrawLine(0, y, w, y)
dc.DrawText(str(tmpNr), 0, y - dc.GetFont().GetPixelSize().GetHeight())
tmpNr += 50
dc.DrawLine(0, 0, w, 0)
dc.DrawLine(0, 0, 0, h)

View File

@ -153,6 +153,7 @@ class projectPlanner(wx.Frame):
self.list = []
self.selection = None
self.printMode = 0
self.alwaysAutoPlace = True
self.machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
self.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
@ -170,8 +171,8 @@ class projectPlanner(wx.Frame):
toolbarUtil.NormalButton(self.toolbar, self.OnSaveProject, 'save.png', 'Save project')
self.toolbar.AddSeparator()
group = []
toolbarUtil.RadioButton(self.toolbar, group, 'object-3d-on.png', 'object-3d-off.png', '3D view', callback=self.On3DClick)
toolbarUtil.RadioButton(self.toolbar, group, 'object-top-on.png', 'object-top-off.png', 'Topdown view', callback=self.OnTopClick).SetValue(True)
toolbarUtil.RadioButton(self.toolbar, group, 'object-3d-on.png', 'object-3d-off.png', '3D view', callback=self.On3DClick).SetValue(self.alwaysAutoPlace)
toolbarUtil.RadioButton(self.toolbar, group, 'object-top-on.png', 'object-top-off.png', 'Topdown view', callback=self.OnTopClick).SetValue(not self.alwaysAutoPlace)
self.toolbar.AddSeparator()
toolbarUtil.NormalButton(self.toolbar, self.OnPreferences, 'preferences.png', 'Project planner preferences')
self.toolbar.AddSeparator()
@ -196,6 +197,7 @@ class projectPlanner(wx.Frame):
toolbarUtil.NormalButton(self.toolbar2, self.OnCopy, 'copy.png', 'Make a copy of the current selected object')
toolbarUtil.NormalButton(self.toolbar2, self.OnSetCustomProfile, 'set-profile.png', 'Set a custom profile to be used to prepare a specific object.')
self.toolbar2.AddSeparator()
if not self.alwaysAutoPlace:
toolbarUtil.NormalButton(self.toolbar2, self.OnAutoPlace, 'autoplace.png', 'Automaticly organize the objects on the platform.')
toolbarUtil.NormalButton(self.toolbar2, self.OnSlice, 'slice.png', 'Prepare to project into a gcode file.')
self.toolbar2.Realize()
@ -218,6 +220,7 @@ class projectPlanner(wx.Frame):
self.addButton = wx.Button(self.panel, -1, "Add")
self.remButton = wx.Button(self.panel, -1, "Remove")
self.sliceButton = wx.Button(self.panel, -1, "Prepare")
if not self.alwaysAutoPlace:
self.autoPlaceButton = wx.Button(self.panel, -1, "Auto Place")
sizer.Add(self.toolbar, (0,0), span=(1,1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT)
@ -228,6 +231,7 @@ class projectPlanner(wx.Frame):
sizer.Add(self.addButton, (3,1), span=(1,1))
sizer.Add(self.remButton, (3,2), span=(1,1))
sizer.Add(self.sliceButton, (4,1), span=(1,1))
if not self.alwaysAutoPlace:
sizer.Add(self.autoPlaceButton, (4,2), span=(1,1))
sizer.AddGrowableCol(0)
sizer.AddGrowableRow(1)
@ -235,6 +239,7 @@ class projectPlanner(wx.Frame):
self.addButton.Bind(wx.EVT_BUTTON, self.OnAddModel)
self.remButton.Bind(wx.EVT_BUTTON, self.OnRemModel)
self.sliceButton.Bind(wx.EVT_BUTTON, self.OnSlice)
if not self.alwaysAutoPlace:
self.autoPlaceButton.Bind(wx.EVT_BUTTON, self.OnAutoPlace)
self.listbox.Bind(wx.EVT_LISTBOX, self.OnListSelect)
@ -309,6 +314,8 @@ class projectPlanner(wx.Frame):
self.printMode = 0
if self.printAllAtOnce.GetValue():
self.printMode = 1
if self.alwaysAutoPlace:
self.OnAutoPlace(None)
self.preview.Refresh()
def OnSaveCombinedSTL(self, e):
@ -508,6 +515,8 @@ class projectPlanner(wx.Frame):
else:
self.selection = None
self.listbox.SetSelection(-1)
if self.alwaysAutoPlace:
self.OnAutoPlace(None)
def OnAutoPlace(self, e):
bestAllowedSize = int(self.machineSize[1])
@ -587,8 +596,8 @@ class projectPlanner(wx.Frame):
for item in self.list:
if item.profile != None and os.path.isfile(item.profile):
profile.loadGlobalProfile(item.profile)
put('machine_center_x', item.centerX - self.extruderOffset[item.extruder][0])
put('machine_center_y', item.centerY - self.extruderOffset[item.extruder][1])
put('object_center_x', item.centerX - self.extruderOffset[item.extruder][0])
put('object_center_y', item.centerY - self.extruderOffset[item.extruder][1])
put('model_scale', item.scale)
put('flip_x', item.flipX)
put('flip_y', item.flipY)
@ -630,8 +639,8 @@ class projectPlanner(wx.Frame):
action = Action()
action.sliceCmd = sliceRun.getSliceCommand(resultFilename + "_temp_.stl")
action.centerX = profile.getProfileSettingFloat('machine_center_x')
action.centerY = profile.getProfileSettingFloat('machine_center_y')
action.centerX = profile.getPreferenceFloat('machine_width') / 2
action.centerY = profile.getPreferenceFloat('machine_depth') / 2
action.temperature = profile.getProfileSettingFloat('print_temperature')
action.extruder = 0
action.filename = resultFilename + "_temp_.stl"
@ -663,6 +672,8 @@ class projectPlanner(wx.Frame):
return
self.selection.rotate = float(self.rotateCtrl.GetValue())
self.selection.updateModelTransform()
if self.alwaysAutoPlace:
self.OnAutoPlace(None)
self.preview.Refresh()
def OnExtruderChange(self, e):
@ -680,6 +691,8 @@ class projectPlanner(wx.Frame):
self.selection.swapXZ = self.swapXZ.GetValue()
self.selection.swapYZ = self.swapYZ.GetValue()
self.selection.updateModelTransform()
if self.alwaysAutoPlace:
self.OnAutoPlace(None)
self.preview.Refresh()
def getExtraHeadSize(self):
@ -717,16 +730,24 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
self.yaw = 30
self.pitch = 60
self.zoom = self.parent.machineSize[0] / 2 + 10
self.offsetX = 0
self.offsetY = 0
self.view3D = False
self.view3D = self.parent.alwaysAutoPlace
if self.view3D:
self.zoom = 300
else:
self.zoom = self.parent.machineSize[0] / 2 + 10
self.allowDrag = False
self.objColor = profile.getPreferenceColour('model_colour')
def OnMouseLeftDown(self,e):
self.allowDrag = True
if not self.parent.alwaysAutoPlace and not self.view3D:
#TODO: Translate mouse X/Y to 3D X/Y/Z
for item in self.parent.list:
iMin = (item.getMinimum() * item.scale) + numpy.array([item.centerX, item.centerY, 0]) - self.parent.extruderOffset[item.extruder]
iMax = (item.getMaximum() * item.scale) + numpy.array([item.centerX, item.centerY, 0]) - self.parent.extruderOffset[item.extruder]
def OnMouseMotion(self,e):
if self.allowDrag and e.Dragging() and e.LeftIsDown():
@ -737,7 +758,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
self.pitch = 170
if self.pitch < 10:
self.pitch = 10
else:
elif not self.parent.alwaysAutoPlace:
item = self.parent.selection
if item != None:
item.centerX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2
@ -851,6 +872,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
glDisable(GL_LIGHTING)
if not self.parent.alwaysAutoPlace:
if self.parent.selection == item:
if item.gotHit:
glColor3f(1.0,0.0,0.3)
@ -964,8 +986,8 @@ class ProjectSliceProgressWindow(wx.Frame):
line = p.stdout.readline()
self.returnCode = p.wait()
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder][0])
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder][1])
put('object_center_x', action.centerX - self.extruderOffset[action.extruder][0])
put('object_center_y', action.centerY - self.extruderOffset[action.extruder][1])
put('clear_z', action.clearZ)
put('extruder', action.extruder)
put('print_temperature', action.temperature)

View File

@ -110,7 +110,7 @@ class simpleModeWindow(configBase.configWindowBase):
sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
# load and slice buttons.
loadButton = wx.Button(self, -1, '&Load Model')
loadButton = wx.Button(self, -1, '&Load model')
sliceButton = wx.Button(self, -1, 'P&repare print')
printButton = wx.Button(self, -1, '&Print')
self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
@ -187,8 +187,6 @@ class simpleModeWindow(configBase.configWindowBase):
put('print_speed', '50')
put('print_temperature', '220')
put('support', 'None')
#put('machine_center_x', '100')
#put('machine_center_y', '100')
put('retraction_enable', 'False')
put('retraction_min_travel', '5.0')
put('retraction_speed', '40.0')

View File

@ -46,8 +46,8 @@ class sliceProgessPanel(wx.Panel):
if idx > 0:
profile.setTempOverride('fan_enabled', 'False')
profile.setTempOverride('skirt_line_count', '0')
profile.setTempOverride('machine_center_x', profile.getProfileSettingFloat('machine_center_x') - profile.getPreferenceFloat('extruder_offset_x%d' % (idx)))
profile.setTempOverride('machine_center_y', profile.getProfileSettingFloat('machine_center_y') - profile.getPreferenceFloat('extruder_offset_y%d' % (idx)))
profile.setTempOverride('object_center_x', profile.getPreferenceFloat('machine_width') / 2 - profile.getPreferenceFloat('extruder_offset_x%d' % (idx)))
profile.setTempOverride('object_center_y', profile.getPreferenceFloat('machine_depth') / 2 - profile.getPreferenceFloat('extruder_offset_y%d' % (idx)))
profile.setTempOverride('alternative_center', self.filelist[0])
if len(self.filelist) > 1:
profile.setTempOverride('add_start_end_gcode', 'False')
@ -183,6 +183,11 @@ class WorkerThread(threading.Thread):
wx.CallAfter(self.notifyWindow.statusText.SetLabel, "Aborted by user.")
return
line = p.stdout.readline()
line = p.stderr.readline()
while(len(line) > 0):
line = line.rstrip()
self.progressLog.append(line)
line = p.stderr.readline()
self.returnCode = p.wait()
self.fileIdx += 1
if self.fileIdx == len(self.cmdList):
@ -220,9 +225,11 @@ class WorkerThread(threading.Thread):
resultFile.write('T%d\n' % (currentExtruder))
layerNr = -1
hasLine = True
filesOrder = files[:]
while hasLine:
hasLine = False
for f in files:
filesOrder.reverse()
for f in filesOrder:
layerHasLine = False
for line in f:
hasLine = True
@ -237,7 +244,7 @@ class WorkerThread(threading.Thread):
if nextExtruder != currentExtruder:
resultFile.write(';TYPE:CUSTOM\n')
profile.setTempOverride('extruder', nextExtruder)
resultFile.write(profile.getAlterationFileContents('switchExtruder.gcode'))
resultFile.write(profile.getAlterationFileContents('switchExtruder.gcode') + '\n')
profile.resetTempOverride()
currentExtruder = nextExtruder
layerHasLine = True

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

View File

@ -28,6 +28,9 @@ class daeModel(mesh.mesh):
for node in self._idMap[instance_visual_scene['_url']]['node']:
self._ProcessNode2(node)
scale = float(self._base['collada'][0]['asset'][0]['unit'][0]['_meter']) * 1000
self.origonalVertexes *= scale
self._base = None
self._cur = None
self._idMap = None

View File

@ -21,3 +21,14 @@ def openExporer(filename):
elif os.path.isfile('/usr/bin/dolphin'):
subprocess.Popen(['/usr/bin/dolphin', os.path.split(filename)[0]])
def openExporerPath(filename):
if sys.platform == 'win32' or sys.platform == 'cygwin':
subprocess.Popen(r'explorer "%s"' % (filename))
if sys.platform == 'darwin':
subprocess.Popen(['open', filename])
if sys.platform.startswith('linux'):
if os.path.isfile('/usr/bin/nautilus'):
subprocess.Popen(['/usr/bin/nautilus', filename])
elif os.path.isfile('/usr/bin/dolphin'):
subprocess.Popen(['/usr/bin/dolphin', filename])

View File

@ -208,6 +208,9 @@ class MachineCom(object):
return self._errorValue
return self._errorValue[:20] + "..."
def getErrorString(self):
return self._errorValue
def isClosedOrError(self):
return self._state == self.STATE_ERROR or self._state == self.STATE_CLOSED_WITH_ERROR or self._state == self.STATE_CLOSED

View File

@ -41,6 +41,7 @@ class mesh(object):
return self.size
def setRotateMirror(self, rotate, mirrorX, mirrorY, mirrorZ, swapXZ, swapYZ):
#Modify the vertexes with the rotation/mirror
rotate = rotate / 180.0 * math.pi
scaleX = 1.0
scaleY = 1.0
@ -63,6 +64,13 @@ class mesh(object):
mat = numpy.array([mat[0],mat[2],mat[1]], numpy.float32)
self.vertexes = (numpy.matrix(self.origonalVertexes, copy = False) * numpy.matrix(mat)).getA()
#Calculate the boundery box of the object
self.getMinimumZ()
#Calculate the boundery circle
center = (self.max + self.min) / 2.0
self.bounderyCircleSize = round(math.sqrt(numpy.max(((self.vertexes[::,0] - center[0]) * (self.vertexes[::,0] - center[0])) + ((self.vertexes[::,1] - center[1]) * (self.vertexes[::,1] - center[1])))), 3)
#Calculate the normals
tris = self.vertexes.reshape(self.vertexCount / 3, 3, 3)
normals = numpy.cross( tris[::,1 ] - tris[::,0] , tris[::,2 ] - tris[::,0] )
lens = numpy.sqrt( normals[:,0]**2 + normals[:,1]**2 + normals[:,2]**2 )
@ -77,8 +85,6 @@ class mesh(object):
self.normal = n.reshape(self.vertexCount, 3)
self.invNormal = -self.normal
self.getMinimumZ()
def splitToParts(self, callback = None):
t0 = time.time()

View File

@ -31,8 +31,6 @@ profileDefaultSettings = {
'support': 'None',
'filament_diameter': '2.89',
'filament_density': '1.00',
'machine_center_x': '100',
'machine_center_y': '100',
'retraction_min_travel': '5.0',
'retraction_enable': 'False',
'retraction_speed': '40.0',
@ -42,7 +40,7 @@ profileDefaultSettings = {
'travel_speed': '150',
'max_z_speed': '3.0',
'bottom_layer_speed': '20',
'cool_min_layer_time': '10',
'cool_min_layer_time': '5',
'fan_enabled': 'True',
'fan_layer': '1',
'fan_speed': '100',
@ -74,6 +72,7 @@ profileDefaultSettings = {
'raft_base_material_amount': '100',
'raft_interface_material_amount': '100',
'bottom_thickness': '0.3',
'hop_on_move': 'False',
'plugin_config': '',
'add_start_end_gcode': 'True',
@ -102,9 +101,6 @@ G1 Z15.0 F{max_z_speed} ;move the platform down 15mm
G92 E0 ;zero the extruded length
G1 F200 E3 ;extrude 3mm of feed stock
G92 E0 ;zero the extruded length again
;go to the middle of the platform (disabled, as there is no need to go to the center)
;G1 X{machine_center_x} Y{machine_center_y} F{travel_speed}
G1 F{travel_speed}
""",
#######################################################################################
@ -137,7 +133,7 @@ G90 ;absolute positioning
G1 Z{clear_z} F{max_z_speed}
G92 E0
G1 X{machine_center_x} Y{machine_center_y} F{travel_speed}
G1 X{object_center_x} Y{object_center_x} F{travel_speed}
G1 F200 E6
G92 E0
""",
@ -158,6 +154,7 @@ preferencesDefaultSettings = {
'machine_depth': '205',
'machine_height': '200',
'machine_type': 'unknown',
'ultimaker_extruder_upgrade': 'False',
'has_heated_bed': 'False',
'extruder_amount': '1',
'extruder_offset_x1': '-22.0',
@ -219,6 +216,13 @@ def resetGlobalProfile():
global globalProfileParser
globalProfileParser = ConfigParser.ConfigParser()
if getPreference('machine_type') == 'ultimaker':
putProfileSetting('nozzle_size', '0.4')
if getPreference('ultimaker_extruder_upgrade') == 'True':
putProfileSetting('retraction_enable', 'True')
else:
putProfileSetting('nozzle_size', '0.5')
def saveGlobalProfile(filename):
#Save the current profile to an ini file
globalProfileParser.write(open(filename, 'w'))
@ -545,9 +549,10 @@ def setPluginConfig(config):
putProfileSetting('plugin_config', pickle.dumps(config))
def getPluginBasePaths():
ret = [os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'plugins'))]
ret = []
if platform.system() != "Windows":
ret.append(os.path.expanduser('~/.cura/plugins/'))
ret.append(os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'plugins')))
return ret
def getPluginList():

View File

@ -26,6 +26,7 @@ sliceStepTimeFactor = {
'dwindle': 1.0,
'comb': 23.7805759907,
'cool': 27.148763895,
'hop': 1.0,
'dimension': 90.4914340973
}
@ -114,7 +115,7 @@ def getSliceCommand(filename):
cmd = [slic3rExe,
'--output-filename-format', '[input_filename_base].gcode',
'--nozzle-diameter', str(profile.calculateEdgeWidth()),
'--print-center', '%s,%s' % (profile.getProfileSetting('machine_center_x'), profile.getProfileSetting('machine_center_y')),
'--print-center', '%s,%s' % (profile.getPreferenceFloat('machine_width') / 2, profile.getPreferenceFloat('machine_depth') / 2),
'--z-offset', '0',
'--gcode-flavor', 'reprap',
'--gcode-comments',

View File

@ -215,7 +215,7 @@ if __name__ == '__main__':
f.write(';TYPE:CUSTOM\n')
f.write(profile.getAlterationFileContents('start.gcode'))
svg.center(complex(profile.getProfileSettingFloat('machine_center_x'), profile.getProfileSettingFloat('machine_center_y')))
svg.center(complex(profile.getPreferenceFloat('machine_width') / 2, profile.getPreferenceFloat('machine_depth') / 2))
layerThickness = 0.4
filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2