Large configuration update, the new UI now starts to work a bit.

Still missing a bunch of configuration settings. And the start/end code is
not editable yet, and never included.
master
Daid 2012-02-20 23:27:34 +01:00
parent 66ed99c4db
commit 68944bb221
4 changed files with 184 additions and 74 deletions

View File

@ -14,7 +14,7 @@ def getSkeinPyPyConfigInformation():
return {
'carve': {
'Add_Layer_Template_to_SVG': 'ignore',
'Edge_Width_mm': 'ignore',
'Edge_Width_mm': 'save',
'Extra_Decimal_Places_float': 'ignore',
'Import_Coarseness_ratio': 'ignore',
'Layer_Height_mm': 'save',
@ -71,7 +71,7 @@ def getSkeinPyPyConfigInformation():
'Line': 'ignore',
'Infill_Perimeter_Overlap_ratio': 'save',
'Infill_Solidity_ratio': 'save',
'Infill_Width': 'save',
'Infill_Width': 'use:carve:Edge_Width_mm',
'Solid_Surface_Thickness_layers': 'save',
'Start_From_Choice': 'ignore',
'Surrounding_Angle_degrees': 'ignore',
@ -92,12 +92,12 @@ def getSkeinPyPyConfigInformation():
'Duty_Cyle_at_Beginning_portion': 'ignore',
'Duty_Cyle_at_Ending_portion': 'ignore',
'Feed_Rate_mm/s': 'save',
'Flow_Rate_Setting_float': 'use:Feed_Rate_mm/s',
'Flow_Rate_Setting_float': 'use:speed:Feed_Rate_mm/s',
'Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio': 'save',
'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': 'use:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': 'use:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Flow_Rate_Infill_Multiplier_ratio': 'use:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Flow_Rate_Perimeter_Multiplier_ratio': 'use:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': 'use:speed:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': 'use:speed:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Flow_Rate_Infill_Multiplier_ratio': 'use:speed:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layer_Flow_Rate_Perimeter_Multiplier_ratio': 'use:speed:Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio',
'Object_First_Layers_Amount_Of_Layers_For_Speed_Change': 'save',
'Orbital_Feed_Rate_over_Operating_Feed_Rate_ratio': 'ignore',
'Maximum_Z_Feed_Rate_mm/s': 'save',
@ -345,7 +345,8 @@ def getReadRepository(repository):
continue
#Load this setting from another value.
if info[name][0:4] == "use:":
p.setValueToString(globalConfigParser.get(repository.name, info[name][4:]))
i = info[name][4:].split(':')
p.setValueToString(globalConfigParser.get(i[0], i[1]))
continue
try:
@ -357,10 +358,35 @@ def getReadRepository(repository):
except:
pass
globalConfigParser.set(repository.name, name, str(p.value))
saveGlobalConfig(getDefaultConfigPath())
#saveGlobalConfig(getDefaultConfigPath())
#print "============" + str(p) + "|" + p.name + "|" + str(p.value) + "|" + str(type(p.value))
return repository
def storeRepository(repository):
"Store the configuration for this 'repository'"
#Check if we have a configuration file loaded, else load the default.
if not globals().has_key('globalConfigParser'):
loadGlobalConfig(getDefaultConfigPath())
info = getSkeinPyPyConfigInformation()
if not info.has_key(repository.name):
print "Warning: Plugin: " + repository.name + " missing from SkeinPyPy info"
return repository
info = info[repository.name]
if not type(info) is dict:
print "Ignoring plugin configuration: " + repository.name
return repository
for p in repository.preferences:
name = safeConfigName(p.name)
if not info.has_key(name):
print "Setting: " + repository.name + ":" + name + " missing from SkeinPyPy info"
continue
if info[name] == "save":
globalConfigParser.set(repository.name, name, str(p.value))
return repository
def printProgress(layerIndex, procedureName):
print("Progress: ", procedureName, layerIndex)
def printProgressByNumber(layerIndex, numberOfLayers, procedureName):
@ -491,7 +517,8 @@ class FloatSpin( FloatSetting ):
"Initialize."
self.name = name
self.value = value
repository.preferences.append(self)
if repository != None:
repository.preferences.append(self)
return self
class LabelSeparator:

View File

@ -1,6 +1,8 @@
from __future__ import absolute_import
import __init__
import skeinpypy
import wx, os
from newui import preview3d
@ -21,62 +23,86 @@ class mainWindow(wx.Frame):
fileMenu = wx.Menu()
fitem = fileMenu.Append(-1, 'Open Profile...', 'Open Profile...')
fitem = fileMenu.Append(-1, 'Save Profile...', 'Save Profile...')
self.Bind(wx.EVT_MENU, self.OnSaveProfile, fitem)
fitem = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quit application')
self.Bind(wx.EVT_MENU, self.OnQuit, fitem)
menubar.Append(fileMenu, '&File')
menubar.Append(wx.Menu(), 'Expert')
self.SetMenuBar(menubar)
plugins = {}
self.filename = None
self.controlList = []
self.plugins = {}
for m in skeinforge_profile.getCraftTypePluginModule().getCraftSequence():
plugins[m] = archive.getModuleWithDirectoryPath(archive.getCraftPluginsDirectoryPath(), m).getNewRepository()
settings.getReadRepository(plugins[m])
p = wx.Panel(self)
nb = wx.Notebook(p, size=(500,10))
printConfig = wx.Panel(nb);
sizer = wx.GridBagSizer(2, 2)
printConfig.SetSizer(sizer)
self.plugins[m] = archive.getModuleWithDirectoryPath(archive.getCraftPluginsDirectoryPath(), m).getNewRepository()
settings.getReadRepository(self.plugins[m])
skeinPyPySettingInfo = settings.getSkeinPyPyConfigInformation()
for pluginName in plugins.keys():
box, configPanel = self.CreateGroup(printConfig, pluginName)
for pref in plugins[pluginName].preferences:
for pluginName in self.plugins.keys():
self.plugins[pluginName].preferencesDict = {}
for pref in self.plugins[pluginName].preferences:
if skeinPyPySettingInfo[pluginName][settings.safeConfigName(pref.name)] == 'save':
self.AddSetting(configPanel, pref.name, wx.TextCtrl(configPanel, -1, str(pref.value)))
self.plugins[pluginName].preferencesDict[settings.safeConfigName(pref.name)] = pref
if configPanel.GetSizer().GetRows() > 0:
sizer.Add(box, (sizer.GetRows(),0))
sizer.SetRows(sizer.GetRows()+1)
p = wx.Panel(self)
nb = wx.Notebook(p, size=(500,10))
#self.AddSetting(generalConfig, "Speed (mm/s)", wx.TextCtrl(generalConfig, -1, "50.0"))
machineConfig = wx.Panel(nb);
configPanel = wx.Panel(nb);
nb.AddPage(configPanel, "Print")
sizer = wx.GridBagSizer(2, 2)
machineConfig.SetSizer(sizer)
box, dimensionsConfig = self.CreateGroup(machineConfig, "Dimensions")
self.AddSetting(dimensionsConfig, "Printer size (mm)", wx.TextCtrl(dimensionsConfig, -1, "205,205,200"))
sizer.Add(box, (0,0))
configPanel.SetSizer(sizer)
self.AddTitle(configPanel, "Accuracy")
self.AddSetting(configPanel, "Layer height (mm)", self.plugins['carve'].preferencesDict['Layer_Height_mm'])
self.AddTitle(configPanel, "Skirt")
self.AddSetting(configPanel, "Enable skirt", self.plugins['skirt'].preferencesDict['Activate_Skirt'])
self.AddSetting(configPanel, "Skirt distance (mm)", self.plugins['skirt'].preferencesDict['Gap_over_Perimeter_Width_ratio'])
self.AddTitle(configPanel, "Fill")
self.AddSetting(configPanel, "Solid layers", self.plugins['fill'].preferencesDict['Solid_Surface_Thickness_layers'])
self.AddSetting(configPanel, "Fill Density", self.plugins['fill'].preferencesDict['Infill_Solidity_ratio'])
self.AddTitle(configPanel, "Retraction")
self.AddSetting(configPanel, "Speed (mm/s)", self.plugins['dimension'].preferencesDict['Extruder_Retraction_Speed_mm/s'])
self.AddSetting(configPanel, "Distance (mm)", self.plugins['dimension'].preferencesDict['Retraction_Distance_millimeters'])
self.AddSetting(configPanel, "Extra length on start (mm)", self.plugins['dimension'].preferencesDict['Restart_Extra_Distance_millimeters'])
configPanel = wx.Panel(nb);
nb.AddPage(configPanel, "Machine")
sizer = wx.GridBagSizer(2, 2)
configPanel.SetSizer(sizer)
self.AddTitle(configPanel, "Machine size")
self.AddSetting(configPanel, "Width (mm)", settings.IntSpin().getFromValue(10, "machine_width", None, 1000, 205))
self.AddSetting(configPanel, "Depth (mm)", settings.IntSpin().getFromValue(10, "machine_depth", None, 1000, 205))
self.AddSetting(configPanel, "Height (mm)", settings.IntSpin().getFromValue(10, "machine_height", None, 1000, 200))
self.AddTitle(configPanel, "Machine nozzle")
self.AddSetting(configPanel, "Nozzle size (mm)", self.plugins['carve'].preferencesDict['Edge_Width_mm'])
self.AddTitle(configPanel, "Speed")
self.AddSetting(configPanel, "Print speed (mm/s)", self.plugins['speed'].preferencesDict['Feed_Rate_mm/s'])
self.AddSetting(configPanel, "Travel speed (mm/s)", self.plugins['speed'].preferencesDict['Travel_Feed_Rate_mm/s'])
self.AddTitle(configPanel, "Filament")
self.AddSetting(configPanel, "Diameter (mm)", self.plugins['dimension'].preferencesDict['Filament_Diameter_mm'])
self.AddSetting(configPanel, "Packing Density", self.plugins['dimension'].preferencesDict['Filament_Packing_Density_ratio'])
nb.AddPage(printConfig, "Print")
nb.AddPage(machineConfig, "Machine")
nb.AddPage(wx.Panel(nb), "Start/End-GCode")
#Preview window, load and slice buttons.
self.preview3d = preview3d.myGLCanvas(p)
loadButton = wx.Button(p, 1, 'Load STL')
loadButton = wx.Button(p, -1, 'Load STL')
sliceButton = wx.Button(p, -1, 'Slice to GCode')
self.Bind(wx.EVT_BUTTON, self.OnLoadSTL, loadButton)
self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
sizer = wx.GridBagSizer()
sizer.Add(nb, (0,0), span=(2,1), flag=wx.EXPAND)
sizer.Add(self.preview3d, (0,1), span=(1,1), flag=wx.EXPAND)
sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
sizer.Add(loadButton, (1,1))
sizer.AddGrowableCol(1)
sizer.Add(sliceButton, (1,2))
sizer.AddGrowableCol(2)
sizer.AddGrowableRow(0)
p.SetSizer(sizer)
@ -84,32 +110,65 @@ class mainWindow(wx.Frame):
self.Centre()
self.Show(True)
def CreateGroup(self, panel, name):
retPanel = wx.Panel(panel)
sizer = wx.GridBagSizer(2, 2)
retPanel.SetSizer(sizer)
box = wx.StaticBox(panel, -1, name)
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
sizer.Add(retPanel)
return (sizer, retPanel)
def AddSetting(self, panel, name, ctrl):
def AddTitle(self, panel, name):
sizer = panel.GetSizer()
sizer.Add(wx.StaticText(panel, -1, name), (sizer.GetRows(),0), flag=wx.ALIGN_BOTTOM)
sizer.Add(ctrl, (sizer.GetRows(),1), flag=wx.ALIGN_BOTTOM|wx.EXPAND)
title = wx.StaticText(panel, -1, name)
title.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
sizer.Add(title, (sizer.GetRows(),1), (1,2), flag=wx.EXPAND)
sizer.Add(wx.StaticLine(panel), (sizer.GetRows()+1,1), (1,2), flag=wx.EXPAND)
sizer.SetRows(sizer.GetRows() + 2)
def AddSetting(self, panel, name, setting):
sizer = panel.GetSizer()
sizer.Add(wx.StaticText(panel, -1, name), (sizer.GetRows(),1), flag=wx.ALIGN_CENTER_VERTICAL)
ctrl = None
if setting.__class__ is settings.FloatSpin:
ctrl = wx.TextCtrl(panel, -1, str(setting.value))
if setting.__class__ is settings.IntSpin:
ctrl = wx.TextCtrl(panel, -1, str(setting.value))
if setting.__class__ is settings.BooleanSetting:
ctrl = wx.CheckBox(panel, -1, '')
ctrl.SetValue(setting.value)
if ctrl == None:
print "No WX control for: " + str(setting), str(setting.__class__)
else:
ctrl.setting = setting
self.controlList.append(ctrl)
sizer.Add(ctrl, (sizer.GetRows(),2), flag=wx.ALIGN_BOTTOM|wx.EXPAND)
sizer.SetRows(sizer.GetRows()+1)
def OnSaveProfile(self, e):
dlg=wx.FileDialog(self, "Select profile file to save", style=wx.FD_SAVE)
dlg.SetWildcard("ini files (*.ini)|*.ini")
if dlg.ShowModal() == wx.ID_OK:
profileFile = dlg.GetPath()
self.updateConfig()
settings.saveGlobalConfig(profileFile)
def OnLoadSTL(self, e):
dlg=wx.FileDialog(self, "Open file to print", style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard("OBJ, STL files (;*.stl;*.STL;*.obj;*.OBJ;)")
dlg.SetWildcard("OBJ, STL files (*.stl;*.STL;*.obj;*.OBJ;)")
if dlg.ShowModal() == wx.ID_OK:
self.filename=dlg.GetPath()
if not(os.path.exists(self.filename)):
return
self.preview3d.loadFile(self.filename)
def OnSlice(self, e):
if self.filename == None:
return
for pluginName in self.plugins.keys():
settings.storeRepository(self.plugins[pluginName])
settings.saveGlobalConfig(settings.getDefaultConfigPath())
skeinpypy.runSkein([self.filename])
def updateConfig(self):
for ctrl in self.controlList:
ctrl.setting.setValueToString(ctrl.GetValue())
for pluginName in self.plugins.keys():
settings.storeRepository(self.plugins[pluginName])
settings.saveGlobalConfig(settings.getDefaultConfigPath())
def OnQuit(self, e):
self.Close()

View File

@ -1,6 +1,6 @@
#from wxPython.glcanvas import wxGLCanvas
import wx
import sys,math
import sys,math,threading
from wx.glcanvas import GLCanvas
try:
@ -24,6 +24,7 @@ class myGLCanvas(GLCanvas):
wx.EVT_MOTION(self, self.OnMouseMotion)
self.init = 0
self.triangleMesh = None
self.modelDisplayList = None
self.yaw = 30
self.pitch = 60
self.zoom = 150
@ -31,8 +32,17 @@ class myGLCanvas(GLCanvas):
self.machineCenter = Vector3(100, 100, 0)
def loadFile(self, filename):
self.triangleMesh = fabmetheus_interpret.getCarving(filename)
self.filename = filename
#Do the STL file loading in a background thread so we don't block the UI.
thread = threading.Thread(target=self.DoLoad)
thread.setDaemon(True)
thread.start()
def DoLoad(self):
self.modelDirty = False
self.triangleMesh = fabmetheus_interpret.getCarving(self.filename)
self.moveModel()
self.Refresh()
def moveModel(self):
if self.triangleMesh == None:
@ -46,6 +56,8 @@ class myGLCanvas(GLCanvas):
v.y -= min.y + (max.y - min.y) / 2
v.x += self.machineCenter.x
v.y += self.machineCenter.y
self.triangleMesh.getMinimumZ()
self.modelDirty = True
def OnMouseMotion(self,e):
if e.Dragging() and e.LeftIsDown():
@ -55,11 +67,12 @@ class myGLCanvas(GLCanvas):
self.pitch = 170
if self.pitch < 10:
self.pitch = 10
self.Refresh()
if e.Dragging() and e.RightIsDown():
self.zoom += e.GetY() - self.oldY
self.Refresh()
self.oldX = e.GetX()
self.oldY = e.GetY()
self.Refresh()
def OnEraseBackground(self,event):
pass
@ -85,18 +98,25 @@ class myGLCanvas(GLCanvas):
glTranslate(-self.machineCenter.x, -self.machineCenter.y, 0)
if self.triangleMesh != None:
glBegin(GL_TRIANGLES)
for face in self.triangleMesh.faces:
v1 = self.triangleMesh.vertexes[face.vertexIndexes[0]]
v2 = self.triangleMesh.vertexes[face.vertexIndexes[1]]
v3 = self.triangleMesh.vertexes[face.vertexIndexes[2]]
normal = (v2 - v1).cross(v3 - v1)
normal.normalize()
glNormal3f(normal.x, normal.y, normal.z)
glVertex3f(v1.x, v1.y, v1.z)
glVertex3f(v2.x, v2.y, v2.z)
glVertex3f(v3.x, v3.y, v3.z)
glEnd()
if self.modelDisplayList == None:
self.modelDisplayList = glGenLists(1);
if self.modelDirty:
self.modelDirty = False
glNewList(self.modelDisplayList, GL_COMPILE)
glBegin(GL_TRIANGLES)
for face in self.triangleMesh.faces:
v1 = self.triangleMesh.vertexes[face.vertexIndexes[0]]
v2 = self.triangleMesh.vertexes[face.vertexIndexes[1]]
v3 = self.triangleMesh.vertexes[face.vertexIndexes[2]]
normal = (v2 - v1).cross(v3 - v1)
normal.normalize()
glNormal3f(normal.x, normal.y, normal.z)
glVertex3f(v1.x, v1.y, v1.z)
glVertex3f(v2.x, v2.y, v2.z)
glVertex3f(v3.x, v3.y, v3.z)
glEnd()
glEndList()
glCallList(self.modelDisplayList)
glLineWidth(4)
glDisable(GL_LIGHTING)
@ -160,6 +180,6 @@ class myGLCanvas(GLCanvas):
glTranslate(0,0,-self.zoom)
glRotate(-self.pitch, 1,0,0)
glRotate(self.yaw, 0,0,1)
#glRotate(90, 1,0,0)
if self.triangleMesh != None:
glTranslate(0,0,-self.triangleMesh.getCarveCornerMaximum().z / 2)
return

View File

@ -13,7 +13,11 @@ from __future__ import absolute_import
from optparse import OptionParser
from skeinforge_application.skeinforge_utilities import skeinforge_craft
from newui import mainWindow
#For some reason the newui import fails when we are importing this from newui.mainWindow (circle references not allowed?) in that case we don't need the UI so skip it.
try:
from newui import mainWindow
except:
pass
import os
import sys
import platform