Script.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # Copyright (c) 2015 Jaime van Kessel
  2. # Copyright (c) 2017 Ultimaker B.V.
  3. # The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
  4. from UM.Logger import Logger
  5. from UM.Signal import Signal, signalemitter
  6. from UM.i18n import i18nCatalog
  7. # Setting stuff import
  8. from UM.Application import Application
  9. from UM.Settings.ContainerStack import ContainerStack
  10. from UM.Settings.InstanceContainer import InstanceContainer
  11. from UM.Settings.DefinitionContainer import DefinitionContainer
  12. from UM.Settings.ContainerRegistry import ContainerRegistry
  13. import re
  14. import json
  15. import collections
  16. i18n_catalog = i18nCatalog("cura")
  17. ## Base class for scripts. All scripts should inherit the script class.
  18. @signalemitter
  19. class Script:
  20. def __init__(self):
  21. super().__init__()
  22. self._settings = None
  23. self._stack = None
  24. setting_data = self.getSettingData()
  25. self._stack = ContainerStack(stack_id = str(id(self)))
  26. self._stack.setDirty(False) # This stack does not need to be saved.
  27. ## Check if the definition of this script already exists. If not, add it to the registry.
  28. if "key" in setting_data:
  29. definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = setting_data["key"])
  30. if definitions:
  31. # Definition was found
  32. self._definition = definitions[0]
  33. else:
  34. self._definition = DefinitionContainer(setting_data["key"])
  35. self._definition.deserialize(json.dumps(setting_data))
  36. ContainerRegistry.getInstance().addContainer(self._definition)
  37. self._stack.addContainer(self._definition)
  38. self._instance = InstanceContainer(container_id="ScriptInstanceContainer")
  39. self._instance.setDefinition(self._definition.getId())
  40. self._instance.addMetaDataEntry("setting_version", self._definition.getMetaDataEntry("setting_version", default = 0))
  41. self._stack.addContainer(self._instance)
  42. self._stack.propertyChanged.connect(self._onPropertyChanged)
  43. ContainerRegistry.getInstance().addContainer(self._stack)
  44. settingsLoaded = Signal()
  45. valueChanged = Signal() # Signal emitted whenever a value of a setting is changed
  46. def _onPropertyChanged(self, key, property_name):
  47. if property_name == "value":
  48. self.valueChanged.emit()
  49. # Property changed: trigger reslice
  50. # To do this we use the global container stack propertyChanged.
  51. # Reslicing is necessary for setting changes in this plugin, because the changes
  52. # are applied only once per "fresh" gcode
  53. global_container_stack = Application.getInstance().getGlobalContainerStack()
  54. global_container_stack.propertyChanged.emit(key, property_name)
  55. ## Needs to return a dict that can be used to construct a settingcategory file.
  56. # See the example script for an example.
  57. # It follows the same style / guides as the Uranium settings.
  58. # Scripts can either override getSettingData directly, or use getSettingDataString
  59. # to return a string that will be parsed as json. The latter has the benefit over
  60. # returning a dict in that the order of settings is maintained.
  61. def getSettingData(self):
  62. setting_data = self.getSettingDataString()
  63. if type(setting_data) == str:
  64. setting_data = json.loads(setting_data, object_pairs_hook = collections.OrderedDict)
  65. return setting_data
  66. def getSettingDataString(self):
  67. raise NotImplementedError()
  68. def getDefinitionId(self):
  69. if self._stack:
  70. return self._stack.getBottom().getId()
  71. def getStackId(self):
  72. if self._stack:
  73. return self._stack.getId()
  74. ## Convenience function that retrieves value of a setting from the stack.
  75. def getSettingValueByKey(self, key):
  76. return self._stack.getProperty(key, "value")
  77. ## Convenience function that finds the value in a line of g-code.
  78. # When requesting key = x from line "G1 X100" the value 100 is returned.
  79. def getValue(self, line, key, default = None):
  80. if not key in line or (';' in line and line.find(key) > line.find(';')):
  81. return default
  82. sub_part = line[line.find(key) + 1:]
  83. m = re.search('^-?[0-9]+\.?[0-9]*', sub_part)
  84. if m is None:
  85. return default
  86. try:
  87. return float(m.group(0))
  88. except:
  89. return default
  90. ## This is called when the script is executed.
  91. # It gets a list of g-code strings and needs to return a (modified) list.
  92. def execute(self, data):
  93. raise NotImplementedError()