Add post processing plugin support.
This commit is contained in:
parent
be86d34403
commit
655eb31f4e
4 changed files with 228 additions and 60 deletions
|
@ -8,6 +8,7 @@ from gui import expertConfig
|
||||||
from gui import preview3d
|
from gui import preview3d
|
||||||
from gui import sliceProgessPanel
|
from gui import sliceProgessPanel
|
||||||
from gui import alterationPanel
|
from gui import alterationPanel
|
||||||
|
from gui import pluginPanel
|
||||||
from gui import preferencesDialog
|
from gui import preferencesDialog
|
||||||
from gui import configWizard
|
from gui import configWizard
|
||||||
from gui import firmwareInstall
|
from gui import firmwareInstall
|
||||||
|
@ -224,31 +225,10 @@ class mainWindow(configBase.configWindowBase):
|
||||||
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.")
|
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, "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.')
|
||||||
|
|
||||||
#Effects page
|
#Plugin page
|
||||||
self.effectList = profile.getEffectsList()
|
self.pluginPanel = pluginPanel.pluginPanel(nb)
|
||||||
if len(self.effectList) > 0:
|
if len(self.pluginPanel.pluginList) > 0:
|
||||||
self.effectPanel = wx.Panel(nb)
|
nb.AddPage(self.pluginPanel, "Plugins")
|
||||||
sizer = wx.GridBagSizer(2, 2)
|
|
||||||
self.effectPanel.SetSizer(sizer)
|
|
||||||
|
|
||||||
effectStringList = []
|
|
||||||
for effect in self.effectList:
|
|
||||||
effectStringList.append(effect['name'])
|
|
||||||
|
|
||||||
self.listbox = wx.ListBox(self.effectPanel, -1, choices=effectStringList)
|
|
||||||
title = wx.StaticText(self.effectPanel, -1, "Effects:")
|
|
||||||
title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
|
|
||||||
addButton = wx.Button(self.effectPanel, -1, '>', style=wx.BU_EXACTFIT)
|
|
||||||
remButton = wx.Button(self.effectPanel, -1, '<', style=wx.BU_EXACTFIT)
|
|
||||||
sizer.Add(self.listbox, (1,0), span=(2,1), border=10, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM)
|
|
||||||
sizer.Add(title, (0,0), border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.TOP)
|
|
||||||
sizer.Add(addButton, (1,1), border=5, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_BOTTOM)
|
|
||||||
sizer.Add(remButton, (2,1), border=5, flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_TOP)
|
|
||||||
|
|
||||||
sizer.AddGrowableCol(2)
|
|
||||||
sizer.AddGrowableRow(1)
|
|
||||||
sizer.AddGrowableRow(2)
|
|
||||||
nb.AddPage(self.effectPanel, "Effects")
|
|
||||||
|
|
||||||
#Alteration page
|
#Alteration page
|
||||||
self.alterationPanel = alterationPanel.alterationPanel(nb)
|
self.alterationPanel = alterationPanel.alterationPanel(nb)
|
||||||
|
@ -498,3 +478,4 @@ class mainWindow(configBase.configWindowBase):
|
||||||
super(mainWindow, self).updateProfileToControls()
|
super(mainWindow, self).updateProfileToControls()
|
||||||
self.preview3d.updateProfileToControls()
|
self.preview3d.updateProfileToControls()
|
||||||
self.alterationPanel.updateProfileToControls()
|
self.alterationPanel.updateProfileToControls()
|
||||||
|
self.pluginPanel.updateProfileToControls()
|
||||||
|
|
140
Cura/gui/pluginPanel.py
Normal file
140
Cura/gui/pluginPanel.py
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
import wx,wx.stc
|
||||||
|
import sys,math,threading,os
|
||||||
|
from wx.lib import scrolledpanel
|
||||||
|
|
||||||
|
from util import profile
|
||||||
|
|
||||||
|
class pluginPanel(wx.Panel):
|
||||||
|
def __init__(self, parent):
|
||||||
|
wx.Panel.__init__(self, parent,-1)
|
||||||
|
#Plugin page
|
||||||
|
self.pluginList = profile.getPluginList()
|
||||||
|
|
||||||
|
sizer = wx.GridBagSizer(2, 2)
|
||||||
|
self.SetSizer(sizer)
|
||||||
|
|
||||||
|
effectStringList = []
|
||||||
|
for effect in self.pluginList:
|
||||||
|
effectStringList.append(effect['name'])
|
||||||
|
|
||||||
|
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))
|
||||||
|
addButton = wx.Button(self, -1, '>', style=wx.BU_EXACTFIT)
|
||||||
|
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)
|
||||||
|
boxsizer.Add(self.pluginEnabledPanel, 1, flag=wx.EXPAND)
|
||||||
|
|
||||||
|
sizer.AddGrowableCol(2)
|
||||||
|
sizer.AddGrowableRow(1)
|
||||||
|
sizer.AddGrowableRow(2)
|
||||||
|
|
||||||
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
self.pluginEnabledPanel.SetSizer(sizer)
|
||||||
|
|
||||||
|
self.Bind(wx.EVT_BUTTON, self.OnAdd, addButton)
|
||||||
|
self.panelList = []
|
||||||
|
self.updateProfileToControls()
|
||||||
|
|
||||||
|
def updateProfileToControls(self):
|
||||||
|
self.pluginConfig = profile.getPluginConfig()
|
||||||
|
for p in self.panelList:
|
||||||
|
p.Show(False)
|
||||||
|
self.pluginEnabledPanel.GetSizer().Detach(p)
|
||||||
|
self.panelList = []
|
||||||
|
for pluginConfig in self.pluginConfig:
|
||||||
|
self._buildPluginPanel(pluginConfig)
|
||||||
|
|
||||||
|
def _buildPluginPanel(self, pluginConfig):
|
||||||
|
plugin = None
|
||||||
|
for pluginTest in self.pluginList:
|
||||||
|
if pluginTest['filename'] == pluginConfig['filename']:
|
||||||
|
plugin = pluginTest
|
||||||
|
if plugin == None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
pluginPanel = wx.Panel(self.pluginEnabledPanel)
|
||||||
|
s = wx.GridBagSizer(2, 2)
|
||||||
|
pluginPanel.SetSizer(s)
|
||||||
|
title = wx.StaticText(pluginPanel, -1, plugin['name'])
|
||||||
|
title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
|
||||||
|
remButton = wx.Button(pluginPanel, -1, 'X', style=wx.BU_EXACTFIT)
|
||||||
|
s.Add(title, pos=(0,0), span=(1,2), flag=wx.ALIGN_BOTTOM|wx.TOP|wx.LEFT|wx.RIGHT, border=5)
|
||||||
|
s.Add(remButton, pos=(0,2), span=(1,1), flag=wx.TOP|wx.LEFT|wx.RIGHT|wx.ALIGN_RIGHT, border=5)
|
||||||
|
s.Add(wx.StaticLine(pluginPanel), pos=(1,0), span=(1,3), flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=3)
|
||||||
|
info = wx.StaticText(pluginPanel, -1, plugin['info'])
|
||||||
|
info.Wrap(300)
|
||||||
|
s.Add(info, pos=(2,0), span=(1,3), flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=3)
|
||||||
|
|
||||||
|
pluginPanel.paramCtrls = {}
|
||||||
|
i = 0
|
||||||
|
for param in plugin['params']:
|
||||||
|
value = param['default']
|
||||||
|
if param['name'] in pluginConfig['params']:
|
||||||
|
value = pluginConfig['params'][param['name']]
|
||||||
|
|
||||||
|
ctrl = wx.TextCtrl(pluginPanel, -1, value)
|
||||||
|
s.Add(wx.StaticText(pluginPanel, -1, param['description']), pos=(3+i,0), span=(1,1), flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL,border=3)
|
||||||
|
s.Add(ctrl, pos=(3+i,2), span=(1,1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=3)
|
||||||
|
|
||||||
|
ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
|
||||||
|
|
||||||
|
pluginPanel.paramCtrls[param['name']] = ctrl
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
s.Add(wx.StaticLine(pluginPanel), pos=(3+i,0), span=(1,3), flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=3)
|
||||||
|
|
||||||
|
self.Bind(wx.EVT_BUTTON, self.OnRem, remButton)
|
||||||
|
|
||||||
|
s.AddGrowableCol(2)
|
||||||
|
pluginPanel.SetBackgroundColour(self.GetParent().GetBackgroundColour())
|
||||||
|
self.pluginEnabledPanel.GetSizer().Add(pluginPanel, flag=wx.EXPAND)
|
||||||
|
self.pluginEnabledPanel.Layout()
|
||||||
|
self.pluginEnabledPanel.SetSize((1,1))
|
||||||
|
self.Layout()
|
||||||
|
self.pluginEnabledPanel.ScrollChildIntoView(pluginPanel)
|
||||||
|
self.panelList.append(pluginPanel)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def OnSettingChange(self, e):
|
||||||
|
for panel in self.panelList:
|
||||||
|
idx = self.panelList.index(panel)
|
||||||
|
for k in panel.paramCtrls.keys():
|
||||||
|
self.pluginConfig[idx]['params'][k] = panel.paramCtrls[k].GetValue()
|
||||||
|
profile.setPluginConfig(self.pluginConfig)
|
||||||
|
|
||||||
|
def OnAdd(self, e):
|
||||||
|
if self.listbox.GetSelection() < 0:
|
||||||
|
return
|
||||||
|
plugin = self.pluginList[self.listbox.GetSelection()]
|
||||||
|
newConfig = {'filename': plugin['filename'], 'params': {}}
|
||||||
|
if not self._buildPluginPanel(newConfig):
|
||||||
|
return
|
||||||
|
self.pluginConfig.append(newConfig)
|
||||||
|
profile.setPluginConfig(self.pluginConfig)
|
||||||
|
|
||||||
|
def OnRem(self, e):
|
||||||
|
panel = e.GetEventObject().GetParent()
|
||||||
|
sizer = self.pluginEnabledPanel.GetSizer()
|
||||||
|
idx = self.panelList.index(panel)
|
||||||
|
|
||||||
|
panel.Show(False)
|
||||||
|
for p in self.panelList:
|
||||||
|
sizer.Detach(p)
|
||||||
|
self.panelList.pop(idx)
|
||||||
|
for p in self.panelList:
|
||||||
|
sizer.Add(p, flag=wx.EXPAND)
|
||||||
|
|
||||||
|
self.pluginEnabledPanel.Layout()
|
||||||
|
self.pluginEnabledPanel.SetSize((1,1))
|
||||||
|
self.Layout()
|
||||||
|
|
||||||
|
self.pluginConfig.pop(idx)
|
||||||
|
profile.setPluginConfig(self.pluginConfig)
|
|
@ -168,7 +168,7 @@ class WorkerThread(threading.Thread):
|
||||||
if logLine.startswith('Model error('):
|
if logLine.startswith('Model error('):
|
||||||
gcodefile.write(';%s\n' % (logLine))
|
gcodefile.write(';%s\n' % (logLine))
|
||||||
gcodefile.close()
|
gcodefile.close()
|
||||||
profile.runPostProcessingEffects(gcodeFilename)
|
profile.runPostProcessingPlugins(gcodeFilename)
|
||||||
self.gcode = gcodeInterpreter.gcode()
|
self.gcode = gcodeInterpreter.gcode()
|
||||||
self.gcode.load(gcodeFilename)
|
self.gcode.load(gcodeFilename)
|
||||||
profile.replaceGCodeTags(gcodeFilename, self.gcode)
|
profile.replaceGCodeTags(gcodeFilename, self.gcode)
|
||||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import division
|
||||||
import __init__
|
import __init__
|
||||||
|
|
||||||
import os, traceback, math, re, zlib, base64, time, sys, platform, glob
|
import os, traceback, math, re, zlib, base64, time, sys, platform, glob
|
||||||
|
import cPickle as pickle
|
||||||
if sys.version_info[0] < 3:
|
if sys.version_info[0] < 3:
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
else:
|
else:
|
||||||
|
@ -73,6 +74,7 @@ profileDefaultSettings = {
|
||||||
'raft_base_material_amount': '100',
|
'raft_base_material_amount': '100',
|
||||||
'raft_interface_material_amount': '100',
|
'raft_interface_material_amount': '100',
|
||||||
'bottom_thickness': '0.3',
|
'bottom_thickness': '0.3',
|
||||||
|
'plugin_config': '',
|
||||||
|
|
||||||
'add_start_end_gcode': 'True',
|
'add_start_end_gcode': 'True',
|
||||||
'gcode_extension': 'gcode',
|
'gcode_extension': 'gcode',
|
||||||
|
@ -531,17 +533,32 @@ def getAlterationFileContents(filename):
|
||||||
alterationContents = ''
|
alterationContents = ''
|
||||||
return unicode(prefix + re.sub("(.)\{([^\}]*)\}", replaceTagMatch, alterationContents).rstrip() + '\n' + postfix).strip().encode('utf-8')
|
return unicode(prefix + re.sub("(.)\{([^\}]*)\}", replaceTagMatch, alterationContents).rstrip() + '\n' + postfix).strip().encode('utf-8')
|
||||||
|
|
||||||
def getEffectBasePath():
|
###### PLUGIN #####
|
||||||
return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'post_process'))
|
|
||||||
|
|
||||||
def getEffectsList():
|
def getPluginConfig():
|
||||||
|
try:
|
||||||
|
return pickle.loads(getProfileSetting('plugin_config'))
|
||||||
|
except:
|
||||||
|
return []
|
||||||
|
|
||||||
|
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'))]
|
||||||
|
if platform.system() != "Windows":
|
||||||
|
ret.append(os.path.expanduser('~/.cura/plugins/'))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def getPluginList():
|
||||||
ret = []
|
ret = []
|
||||||
for filename in glob.glob(os.path.join(getEffectBasePath(), '*.py')):
|
for basePath in getPluginBasePaths():
|
||||||
|
for filename in glob.glob(os.path.join(basePath, '*.py')):
|
||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
if filename.startswith('_'):
|
if filename.startswith('_'):
|
||||||
continue
|
continue
|
||||||
with open(os.path.join(getEffectBasePath(), filename), "r") as f:
|
with open(os.path.join(basePath, filename), "r") as f:
|
||||||
item = {'name': None, 'info': None, 'params': []}
|
item = {'filename': filename, 'name': None, 'info': None, 'type': None, 'params': []}
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line.startswith('#'):
|
if not line.startswith('#'):
|
||||||
|
@ -553,19 +570,49 @@ def getEffectsList():
|
||||||
item['name'] = line[1].strip()
|
item['name'] = line[1].strip()
|
||||||
elif line[0].upper() == 'INFO':
|
elif line[0].upper() == 'INFO':
|
||||||
item['info'] = line[1].strip()
|
item['info'] = line[1].strip()
|
||||||
|
elif line[0].upper() == 'TYPE':
|
||||||
|
item['type'] = line[1].strip()
|
||||||
elif line[0].upper() == 'PARAM':
|
elif line[0].upper() == 'PARAM':
|
||||||
m = re.match('([a-zA-Z]*)\(([a-zA-Z_]*)\) +(.*)', line[1].strip())
|
m = re.match('([a-zA-Z]*)\(([a-zA-Z_]*)(?:\:([^\)]*))?\) +(.*)', line[1].strip())
|
||||||
if m != None:
|
if m != None:
|
||||||
item['params'].append({'name': m.group(1), 'type': m.group(2), 'description': m.group(3)})
|
item['params'].append({'name': m.group(1), 'type': m.group(2), 'default': m.group(3), 'description': m.group(4)})
|
||||||
else:
|
else:
|
||||||
print "Unknown item in effect meta data: %s %s" % (line[0], line[1])
|
print "Unknown item in effect meta data: %s %s" % (line[0], line[1])
|
||||||
if item['name'] != None:
|
if item['name'] != None and item['type'] == 'postprocess':
|
||||||
ret.append(item)
|
ret.append(item)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def runPostProcessingEffects(filename):
|
def runPostProcessingPlugins(gcodefilename):
|
||||||
pass
|
pluginConfigList = getPluginConfig()
|
||||||
#print "runPostProcessingEffects: %s" % (filename)
|
pluginList = getPluginList()
|
||||||
|
|
||||||
#pythonFile = os.path.join(getEffectBasePath(), 'embedImage.py')
|
for pluginConfig in pluginConfigList:
|
||||||
#execfile(pythonFile, {'filename': filename})
|
plugin = None
|
||||||
|
for pluginTest in pluginList:
|
||||||
|
if pluginTest['filename'] == pluginConfig['filename']:
|
||||||
|
plugin = pluginTest
|
||||||
|
if plugin == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
pythonFile = None
|
||||||
|
for basePath in getPluginBasePaths():
|
||||||
|
testFilename = os.path.join(basePath, pluginConfig['filename'])
|
||||||
|
if os.path.isfile(testFilename):
|
||||||
|
pythonFile = testFilename
|
||||||
|
if pythonFile == None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
locals = {'filename': gcodefilename}
|
||||||
|
for param in plugin['params']:
|
||||||
|
value = param['default']
|
||||||
|
if param['name'] in pluginConfig['params']:
|
||||||
|
value = pluginConfig['params'][param['name']]
|
||||||
|
|
||||||
|
if param['type'] == 'float':
|
||||||
|
try:
|
||||||
|
value = float(value)
|
||||||
|
except:
|
||||||
|
value = 0.0
|
||||||
|
|
||||||
|
locals[param['name']] = value
|
||||||
|
execfile(pythonFile, locals)
|
||||||
|
|
Loading…
Reference in a new issue