Skip to content

Commit

Permalink
TransformEditor, +swap_xy
Browse files Browse the repository at this point in the history
  • Loading branch information
tatarize committed Feb 25, 2020
1 parent df7ad72 commit 29d2856
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 16 deletions.
2 changes: 1 addition & 1 deletion LaserCommandConstants.py
Expand Up @@ -8,7 +8,7 @@
'Rapid' implies the command is performed in default mode.
'Cut' implies the laser is on for the command.
'Shift' implies the laser is off for this command.
'Simple' means the movement must be an octent move. Either +-x, +-y, or +-x and +-y where abs(x) == abs(y).
'Simple' means the movement must be an octant move. Either +-x, +-y, or +-x and +-y where abs(x) == abs(y).
Move alone doesn't imply anything about the laser mode.
Expand Down
21 changes: 14 additions & 7 deletions LhymicroInterpreter.py
Expand Up @@ -43,6 +43,7 @@ def lhymicro_distance(v):
class LhymicroInterpreter(Interpreter):
def __init__(self, device):
Interpreter.__init__(self, device)
self.device.setting(bool, "swap_xy", False)
self.device.setting(bool, "flip_x", False)
self.device.setting(bool, "flip_y", False)
self.device.setting(bool, "home_right", False)
Expand Down Expand Up @@ -91,18 +92,24 @@ def __repr__(self):
return "LhymicroInterpreter()"

def update_codes(self):
if not self.device.flip_x:
if not self.device.swap_xy:
self.CODE_RIGHT = b'B'
self.CODE_LEFT = b'T'
else:
self.CODE_RIGHT = b'T'
self.CODE_LEFT = b'B'
if not self.device.flip_y:
self.CODE_TOP = b'L'
self.CODE_BOTTOM = b'R'
else:
self.CODE_TOP = b'R'
self.CODE_BOTTOM = b'L'
self.CODE_RIGHT = b'R'
self.CODE_LEFT = b'L'
self.CODE_TOP = b'T'
self.CODE_BOTTOM = b'B'
if self.device.flip_x:
q = self.CODE_LEFT
self.CODE_LEFT = self.CODE_RIGHT
self.CODE_RIGHT = q
if self.device.flip_y:
q = self.CODE_TOP
self.CODE_TOP = self.CODE_BOTTOM
self.CODE_BOTTOM = q

def on_plot(self, x, y, on):
self.device.signal('interpreter;plot', (x, y, on))
Expand Down
10 changes: 10 additions & 0 deletions Preferences.py
Expand Up @@ -22,6 +22,7 @@ def __init__(self, *args, **kwds):
self.checkbox_home_right = wx.CheckBox(self, wx.ID_ANY, _("Homes Right"))
self.checkbox_flip_y = wx.CheckBox(self, wx.ID_ANY, _("Flip Y"))
self.checkbox_home_bottom = wx.CheckBox(self, wx.ID_ANY, _("Homes Bottom"))
self.checkbox_swap_xy = wx.CheckBox(self, wx.ID_ANY, _("Swap X and Y"))
self.checkbox_mock_usb = wx.CheckBox(self, wx.ID_ANY, _("Mock USB Connection Mode"))
self.spin_device_index = wx.SpinCtrl(self, wx.ID_ANY, "-1", min=-1, max=5)
self.spin_device_address = wx.SpinCtrl(self, wx.ID_ANY, "-1", min=-1, max=5)
Expand All @@ -40,6 +41,7 @@ def __init__(self, *args, **kwds):
self.__do_layout()

self.Bind(wx.EVT_COMBOBOX, self.on_combobox_boardtype, self.combobox_board)
self.Bind(wx.EVT_CHECKBOX, self.on_check_swap_xy, self.checkbox_swap_xy)
self.Bind(wx.EVT_CHECKBOX, self.on_check_flip_x, self.checkbox_flip_x)
self.Bind(wx.EVT_CHECKBOX, self.on_check_home_right, self.checkbox_home_right)
self.Bind(wx.EVT_CHECKBOX, self.on_check_flip_y, self.checkbox_flip_y)
Expand Down Expand Up @@ -96,6 +98,7 @@ def set_kernel(self, kernel):
dlg.Destroy()
return

self.device.setting(bool, "swap_xy", False)
self.device.setting(bool, "flip_x", False)
self.device.setting(bool, "flip_y", False)
self.device.setting(bool, "home_right", False)
Expand All @@ -116,6 +119,7 @@ def set_kernel(self, kernel):
self.device.setting(int, "usb_address", -1)
self.device.setting(int, "usb_version", -1)

self.checkbox_swap_xy.SetValue(self.device.swap_xy)
self.checkbox_flip_x.SetValue(self.device.flip_x)
self.checkbox_flip_y.SetValue(self.device.flip_y)
self.checkbox_home_right.SetValue(self.device.home_right)
Expand All @@ -139,6 +143,7 @@ def __set_properties(self):
self.SetTitle(_("Preferences"))
self.combobox_board.SetToolTip(_("Select the board to use. This has affects the speedcodes used."))
self.combobox_board.SetSelection(0)
self.checkbox_swap_xy.SetToolTip(_("Swaps the X and Y axis. This happens before the FlipX and FlipY."))
self.checkbox_flip_x.SetToolTip(_("Flip the Right and Left commands sent to the controller"))
self.checkbox_home_right.SetToolTip(_("Indicates the device Home is on the right"))
self.checkbox_flip_y.SetToolTip(_("Flip the Top and Bottom commands sent to the controller"))
Expand Down Expand Up @@ -187,6 +192,7 @@ def __do_layout(self):
sizer_16.Add(self.checkbox_flip_y, 0, 0, 0)
sizer_16.Add(self.checkbox_home_bottom, 0, 0, 0)
sizer_board.Add(sizer_16, 1, wx.EXPAND, 0)
sizer_board.Add(self.checkbox_swap_xy, 0, 0, 0)
sizer_1.Add(sizer_board, 1, wx.EXPAND, 0)
sizer_usb.Add(self.checkbox_mock_usb, 0, 0, 0)
label_6 = wx.StaticText(self, wx.ID_ANY, _("Device Index:"))
Expand Down Expand Up @@ -252,6 +258,10 @@ def calc_home_position(self):
def on_combobox_boardtype(self, event): # wxGlade: Preferences.<event_handler>
self.device.board = self.combobox_board.GetValue()

def on_check_swap_xy(self, event): # wxGlade: Preferences.<event_handler>
self.device.swap_xy = self.checkbox_swap_xy.GetValue()
self.device.execute("Update Codes")

def on_check_flip_x(self, event): # wxGlade: Preferences.<event_handler>
self.device.flip_x = self.checkbox_flip_x.GetValue()
self.device.execute("Update Codes")
Expand Down
19 changes: 14 additions & 5 deletions TextProperty.py
Expand Up @@ -85,7 +85,7 @@ def __init__(self, *args, **kwds):
self.Bind(wx.EVT_CLOSE, self.on_close, self)

def on_close(self, event):
self.kernel.mark_window_closed("PathProperty")
self.kernel.mark_window_closed("TextProperty")
event.Skip() # Call destroy.

def set_element(self, element):
Expand Down Expand Up @@ -188,19 +188,28 @@ def __do_layout(self):
# end wxGlade

def on_combo_font_size(self, event): # wxGlade: TextProperty.<event_handler>
event.Skip()
pass

def on_combo_font(self, event): # wxGlade: TextProperty.<event_handler>
event.Skip()

def on_button_bold(self, event): # wxGlade: TextProperty.<event_handler>
event.Skip()
dialog = wx.FontDialog(None, wx.FontData())
if dialog.ShowModal() == wx.ID_OK:
data = dialog.GetFontData()
font = data.GetChosenFont()
color = data.GetColour()
print(color)
print('"%s", %d pt\n' % (font.GetFaceName(), font.GetPointSize()))
dialog.Destroy()

def on_button_italic(self, event): # wxGlade: TextProperty.<event_handler>
event.Skip()
font_picker = wx.FontDialog()
font_picker.Show()

def on_button_underline(self, event): # wxGlade: TextProperty.<event_handler>
event.Skip()
font_picker = wx.FontDialog()
font_picker.Show()

def on_text_name_change(self, event): # wxGlade: ElementProperty.<event_handler>
try:
Expand Down
160 changes: 160 additions & 0 deletions TransformEditor.py
@@ -0,0 +1,160 @@
import wx

from icons import *
from svgelements import Angle

_ = wx.GetTranslation


class TransformEditor(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: TransformEditor.__init__
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE | wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((364, 299))
self.text_a = wx.TextCtrl(self, wx.ID_ANY, "1.0")
self.text_c = wx.TextCtrl(self, wx.ID_ANY, "0.0")
self.text_b = wx.TextCtrl(self, wx.ID_ANY, "0.0")
self.text_d = wx.TextCtrl(self, wx.ID_ANY, "1.0")
self.text_e = wx.TextCtrl(self, wx.ID_ANY, "0.0")
self.text_f = wx.TextCtrl(self, wx.ID_ANY, "0.0")
self.button_scale_down = wx.BitmapButton(self, wx.ID_ANY, icons8_compress_50.GetBitmap())
self.button_translate_up = wx.BitmapButton(self, wx.ID_ANY, icons8up.GetBitmap())
self.button_scale_up = wx.BitmapButton(self, wx.ID_ANY, icons8_enlarge_50.GetBitmap())
self.button_translate_left = wx.BitmapButton(self, wx.ID_ANY, icons8_left_50.GetBitmap())
self.button_reset = wx.BitmapButton(self, wx.ID_ANY, icons8_delete_50.GetBitmap())
self.button_translate_right = wx.BitmapButton(self, wx.ID_ANY, icons8_right_50.GetBitmap())
self.button_rotate_ccw = wx.BitmapButton(self, wx.ID_ANY, icons8_rotate_left_50.GetBitmap())
self.button_translate_down = wx.BitmapButton(self, wx.ID_ANY, icons8_down_50.GetBitmap())
self.button_translate_cw = wx.BitmapButton(self, wx.ID_ANY, icons8_rotate_right_50.GetBitmap())

self.__set_properties()
self.__do_layout()

self.Bind(wx.EVT_TEXT, self.on_text_matrix, self.text_a)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_matrix, self.text_a)
self.Bind(wx.EVT_TEXT, self.on_text_matrix, self.text_c)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_matrix, self.text_c)
self.Bind(wx.EVT_TEXT, self.on_text_matrix, self.text_b)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_matrix, self.text_b)
self.Bind(wx.EVT_TEXT, self.on_text_matrix, self.text_d)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_matrix, self.text_d)
self.Bind(wx.EVT_TEXT, self.on_text_matrix, self.text_e)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_matrix, self.text_e)
self.Bind(wx.EVT_TEXT, self.on_text_matrix, self.text_f)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_matrix, self.text_f)
self.Bind(wx.EVT_BUTTON, self.on_scale_down, self.button_scale_down)
self.Bind(wx.EVT_BUTTON, self.on_translate_up, self.button_translate_up)
self.Bind(wx.EVT_BUTTON, self.on_scale_up, self.button_scale_up)
self.Bind(wx.EVT_BUTTON, self.on_translate_left, self.button_translate_left)
self.Bind(wx.EVT_BUTTON, self.on_reset, self.button_reset)
self.Bind(wx.EVT_BUTTON, self.on_translate_right, self.button_translate_right)
self.Bind(wx.EVT_BUTTON, self.on_rotate_ccw, self.button_rotate_ccw)
self.Bind(wx.EVT_BUTTON, self.on_translate_down, self.button_translate_down)
self.Bind(wx.EVT_BUTTON, self.on_rotate_cw, self.button_translate_cw)
# end wxGlade
self.kernel = None
self.transform = None
self.Bind(wx.EVT_CLOSE, self.on_close, self)

def on_close(self, event):
self.kernel.mark_window_closed("TransformEditor")
event.Skip() # Call destroy.

def set_kernel(self, kernel):
self.kernel = kernel
self.set_transform(None)

def set_transform(self, transform):
if transform is None:
for attr in dir(self):
value = getattr(self, attr)
if isinstance(value, wx.Control):
value.Enable(False)
else:
for attr in dir(self):
value = getattr(self, attr)
if isinstance(value, wx.Control):
value.Enable(True)

def __set_properties(self):
# begin wxGlade: TransformEditor.__set_properties
self.SetTitle(_("TransformEditor"))
self.button_scale_down.SetSize(self.button_scale_down.GetBestSize())
self.button_translate_up.SetSize(self.button_translate_up.GetBestSize())
self.button_scale_up.SetSize(self.button_scale_up.GetBestSize())
self.button_translate_left.SetSize(self.button_translate_left.GetBestSize())
self.button_reset.SetSize(self.button_reset.GetBestSize())
self.button_translate_right.SetSize(self.button_translate_right.GetBestSize())
self.button_rotate_ccw.SetSize(self.button_rotate_ccw.GetBestSize())
self.button_translate_down.SetSize(self.button_translate_down.GetBestSize())
self.button_translate_cw.SetSize(self.button_translate_cw.GetBestSize())
# end wxGlade

def __do_layout(self):
# begin wxGlade: TransformEditor.__do_layout
sizer_1 = wx.BoxSizer(wx.VERTICAL)
grid_sizer_2 = wx.FlexGridSizer(3, 3, 0, 0)
grid_sizer_1 = wx.FlexGridSizer(3, 3, 0, 0)
grid_sizer_1.Add(self.text_a, 0, 0, 0)
grid_sizer_1.Add(self.text_c, 0, 0, 0)
grid_sizer_1.Add((0, 0), 0, 0, 0)
grid_sizer_1.Add(self.text_b, 0, 0, 0)
grid_sizer_1.Add(self.text_d, 0, 0, 0)
grid_sizer_1.Add((0, 0), 0, 0, 0)
grid_sizer_1.Add((0, 0), 0, 0, 0)
grid_sizer_1.Add(self.text_e, 0, 0, 0)
grid_sizer_1.Add(self.text_f, 0, 0, 0)
sizer_1.Add(grid_sizer_1, 0, wx.EXPAND, 0)
grid_sizer_2.Add(self.button_scale_down, 0, 0, 0)
grid_sizer_2.Add(self.button_translate_up, 0, 0, 0)
grid_sizer_2.Add(self.button_scale_up, 0, 0, 0)
grid_sizer_2.Add(self.button_translate_left, 0, 0, 0)
grid_sizer_2.Add(self.button_reset, 0, 0, 0)
grid_sizer_2.Add(self.button_translate_right, 0, 0, 0)
grid_sizer_2.Add(self.button_rotate_ccw, 0, 0, 0)
grid_sizer_2.Add(self.button_translate_down, 0, 0, 0)
grid_sizer_2.Add(self.button_translate_cw, 0, 0, 0)
sizer_1.Add(grid_sizer_2, 0, wx.EXPAND, 0)
self.SetSizer(sizer_1)
self.Layout()
# end wxGlade

def on_text_matrix(self, event): # wxGlade: TransformEditor.<event_handler>
print(event.Id)

def on_scale_down(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_scale(0.99)
self.kernel.signal("refresh_scene")

def on_translate_up(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_translate(0, -1)
self.kernel.signal("refresh_scene")

def on_scale_up(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_scale(1.01)
self.kernel.signal("refresh_scene")

def on_translate_left(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_translate(-1, 0)
self.kernel.signal("refresh_scene")

def on_reset(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.reset()
self.kernel.signal("refresh_scene")

def on_translate_right(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_translate(1, 0)
self.kernel.signal("refresh_scene")

def on_rotate_ccw(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_rotate(Angle.degrees(-1))
self.kernel.signal("refresh_scene")

def on_translate_down(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_translate(0, 1)
self.kernel.signal("refresh_scene")

def on_rotate_cw(self, event): # wxGlade: TransformEditor.<event_handler>
self.transform.post_rotate(Angle.degrees(1))
self.kernel.signal("refresh_scene")
70 changes: 69 additions & 1 deletion icons.py
Expand Up @@ -1135,4 +1135,72 @@
b'mUlEQVRoge3WOwrCQBRG4YMbmCzBrbsGS+1sfGDlAlxKLMLtBCEjucPlfJA2/AeGYUCSJEna'
b'UAOOwCF7SI8G3IAZeCRvWa0BV5aIN7BPXbNSmYg4TkZkmjBiDBNwx4h8ZSKeLBGZ3+XX0F1/'
b'6ybmf/ykxNEKJa7dYMyoSryzQonnezBmVOVi4gJ4JW/p1oATcM4eIkmSJH31AQ6pXcrw+RVm'
b'AAAAAElFTkSuQmCC')
b'AAAAAElFTkSuQmCC')


icons8_compress_50 = PyEmbeddedImage(
b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAARnQU1B'
b'AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHKSURBVGhD7ZpNSgQxEEZnpd7DlUtd'
b'ewPXHsITeCfx/xe8kzcQtR5OQ1GkeyZRqC9DHnww0yjUo7rpJDWrwWAAB5aj3495HFrO1znl'
b'QiX7ljfLh+WEC1lcWL7XeeZCBUi8Wqb/RyatM60iexYvQegMt1kKLSJIvFiiBB1Ko1akJEFn'
b'UiWgRgSJJ0uU4Ho624qUJPh7CQnYRoRiHy2yErBJhGIfLF4CKSkJWBKh2HuLvATMiVDsncVL'
b'0BlJCSiJUOytxUvQGVkJiCIUe+OuETojLQFe5N1y7b4TOiMvAV7ky30mdKYLCfAiPnSmGwko'
b'iXxaeC6uKiOzH/lrzixp7IzIseXyn8K2edAdtK3UzpZwO6XBg1R6wFrCA57Gzojwsim9hJbC'
b'S42Xm5RILSwv4gKwOxEk4lLcLwi7EEEiboroDEv0bkSQiNvTaSnOpqkLEYqNBwV+U9SFCMXG'
b'I5u4PZUXodh4eFY6KJAWKUnMHdnIilCsL44sHZ5JipQkOGCekwA5EYqNkyKKXJIAKZE4syMM'
b'XTZJgIzIND1tkQAJEQaMUaJ2UiQhwsiX0a+XqJ3Zydxa7EeQaZ2e8mOA6YcB6acddCZtjj0Y'
b'yLBa/QCFElub65nNHQAAAABJRU5ErkJggg==')

#----------------------------------------------------------------------
icons8_enlarge_50 = PyEmbeddedImage(
b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAARnQU1B'
b'AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEVSURBVGhD7dldCoJQEIZhr4r2EBHd'
b'd9Xi21VELaDOCwki/hznTMcZmRe+i4SEB8JEmyiKomhL7dJuyjukVe+U9lHeNa16m4Ec0x7C'
b'vdLMQKTt0+5priFTCOYCMoTg87vz2TxkDMHxZ+eYacgUglxA5hBkHpKDINOQXASZhSxBkEnI'
b'UgSpQbiLvfx25oAwCYLUIHy5PREnlSRFkBlICYJMQEoRtDpEA0GrQrQQtBpEE0GrQLQRxCW/'
b'vfzzVyAuF/IPhGo5EPMImoO4QNAUxA2CxiCuEDQEcYegPsQlgroQHs24RFAX0p8bBI1BXCFo'
b'DMKD5qEH0DnjAXf1pn5a0vHKoXqbgfC6a+g1WMmK7mKjKIoiQzXNF/nEYloeaSPOAAAAAElF'
b'TkSuQmCC')

#----------------------------------------------------------------------
icons8_rotate_left_50 = PyEmbeddedImage(
b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAARnQU1B'
b'AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANgSURBVGhD7ZlLyA1hGMePO4Xo27gU'
b'uSwkt5S7FDbuC5KiWLmVz20hsVZkoSgLOxulSBELt40Fio1yXZDLQoqk3In/75x56u0035mZ'
b'875z5pyaX/06c55v3need843720qJSUlhTJTrq8ddg7T5GE5uvqtxmn5r3bYGZyTJIxbCUQk'
b'NeSEvJFBzg/OoOgTtkhryCUCEQflg9phLHeklUsj5wdjmDwvb8peBER/+Ubek3sIpKSwhgyW'
b'L6RVvFkaQ6PPLDRqyFm5rc41MhhHpF3sAgEP3Ia8do7xq1wmg9Iv+gT+nbhbh6JjH9yGbJLd'
b'8qcTozFzZBBGyGdydfVbWNyGbCQglksaYPEPcoz0gjtOt0eFf2SWBzkNcQ2BpdL9ZW7L3rJp'
b'uBNvpVW4W4akp4bAdml/wx3SC3ojBjZ3fAhFo4YA17S/v5dDpDd9os+QJDVklPwi7ZwDMhMk'
b'fUbOqn7Lj6SGwDFp57yUmZ4Veg4rfI1ATrhzrSUEYhgpf0nLZ7FMjU320HfQC4H1nHicQFoW'
b'yVPyuezpJ28l9FjWkIcEmsF39A4BCzRryA/ZV3YkzK7d52SiTGSSPBq5l0CbwDhiDZlPIImV'
b'0go8ItAmMN+zvOhVE3Eb8phAm/BEWl4rCCSxUFoB5lntwjtpeZFjIjxIVoAZLw9a0QyU5GJ5'
b'jZOJ0LW5U2i2eYpmhrR86H5Tz/vuSyu4i0DB0HtaPncJpIWu1wpeJ1AwLKwsH/YMUjNXWsG/'
b'0nup6cFYSQ6WT+YZudtv57LDlxLmfJYHXXBmdkqrgM0A7kyroXf6Li0P9rYyQ5fnrtevyFbC'
b'ZJW1kF2ffa+mh4IN0ipC9p1axX7pXnut9IJfwipjfMljf6setkbdATDIxkeXdLczeV5Wybyg'
b'bneD7pUcLoMwVX6WVvlvySAVctFFXfskddt1uCbXDso8+UnaRfCqTDXvSWC8dB9s/Chny1yY'
b'Iut3zb/Jk7KZ7pkylKUOt062fSbLXOGZuSzdCyOjLy9/2B+eLgfIeogxAeScW9Idsc2LkpdJ'
b'LYO3tbylqk/EpNdhHGI0Ro7jEjf5pdfJQuAOMwN4KuOSSyNlGbHbYd1ThRcyzEx5j8iaIS5p'
b'5G+cw7l5b8l6w8JngmRJyuszXCDpnfLYDC8pKWlIpfIfTyNhWWO84TIAAAAASUVORK5CYII=')

#----------------------------------------------------------------------
icons8_rotate_right_50 = PyEmbeddedImage(
b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAARnQU1B'
b'AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANbSURBVGhD7ZlLyA9RGIc/d0oiC7Jw'
b'T5Jbyi2ykOS+ICmKjegr95VYk4VSFFmyUIoUodxKFigLKdeFexaKWLgTv+f/n7dO03zN9cyM'
b'mqee/uM158x7vpk5t+loaGioBavltPbh/81febR92GKo3Csnt/7lmUPyago5vyvCDdkoieEp'
b'Aj65Je1iSeT8rrgnd7cPW5yTVm4DgYB+wW+hFNmQMNvlHfla9iYguslr8rQcSKAoVshNIU/K'
b'qEZgmoYYA4JfWC+trmeyv/TCMvlFusm/co6zNMTljLS69hPwwUz5Q9qFON4i1zmxvA3h0doj'
b'TwTHRq/gNzcj5XtpCXNXFkpYK4tqSBTL5RNJd52LHvKmtGS5E/Ol4bMhdAi/JXXTCbh3KTU8'
b'PpYo0v+7+GzINml1v5HDZSboUdxHipcxjO9Hi/GGgdTt3VLDAGZJfpbDZBjfDeHRzkV3+VJa'
b'kgdkFL4b4jJdHpepGrdAWoI/5RAZBS9+krlWXi5Jy2cxgaQclFbwMoGKcQfLYwSScl9awc0E'
b'KoZH+Kk8IucRSEJPyeNkDZkqqybTGDJOWiMYAAubIpTNXGkNeUegJuyQ9J44nkAc9ArWkMcE'
b'asIDaXktJRAHJ1mBhwRqwiNpeS0hEIf7aDHHqQtvpeVFjrGMlVaA2actRaukr7SZMI6SsdD9'
b'uouoUrZsYmAIsHy+y8TTlLvSCjKVrxp6LMvnNoGk0MVZwSsEKuaGtHz2EUjKLGkF/8jMi5oC'
b'GCHJwfJhFpwK1spW2OfMNg7mV5YHXXBqOqVVwIYDf5myoXf6Ji0P9tZSQ5fHOGKVXJBlwkTR'
b'XYewh5Z5KFgjrSLcKstil3SvvVLmgjthlTG+sNfkG7Zr3QGQTYjcDJbu1ijvC9unvghvzb6Q'
b'g2QhTJKfpFX+SzJI5do0C0FdOyV123W4JtculNnyo7SL4EWZaN4Tw2jpvtj4Qc6QXpgo3ccM'
b'v8rDMkv3TBnKUodb53M5QXqFd+a8dC+MjL7s0bJnO0X2kWGIMQHknOvSHbHNs7LQDz1x8KWW'
b'L07hREx6HcYhRmPkOCpxkzu9SlYCf2FmACyJo5JLImUZseuw7mnBxyBmpnwbZM0QlTTyf5zD'
b'uakngGXDwmeMZEm6KHCOpHfKvTHd0NCQlo6Of9ewYWPOK1cIAAAAAElFTkSuQmCC')

0 comments on commit 29d2856

Please sign in to comment.