From d01cddea79cf5b8396be473cc2c5e75f56937ef2 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Thu, 29 Oct 2020 02:56:56 +0200 Subject: [PATCH] - added icons in most application Tools - updated Punch Gerber Tool such that the aperture table is updated upon clicking of the checboxes in Processed Pads Type --- CHANGELOG.md | 5 ++ appTools/ToolCopperThieving.py | 3 + appTools/ToolCorners.py | 1 + appTools/ToolDblSided.py | 2 + appTools/ToolEtchCompensation.py | 1 + appTools/ToolExtractDrills.py | 1 + appTools/ToolFiducials.py | 1 + appTools/ToolInvertGerber.py | 1 + appTools/ToolOptimal.py | 1 + appTools/ToolPanelize.py | 34 ++++++----- appTools/ToolPunchGerber.py | 57 ++++++++++++++++-- appTools/ToolQRCode.py | 1 + appTools/ToolRulesCheck.py | 1 + appTools/ToolSub.py | 2 + assets/resources/dark_resources/pattern32.png | Bin 0 -> 1608 bytes assets/resources/dark_resources/robber32.png | Bin 0 -> 1172 bytes .../dark_resources/subtract_btn32.png | Bin 0 -> 915 bytes assets/resources/pattern32.png | Bin 0 -> 1288 bytes assets/resources/robber32.png | Bin 0 -> 986 bytes assets/resources/subtract_btn32.png | Bin 0 -> 791 bytes 20 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 assets/resources/dark_resources/pattern32.png create mode 100644 assets/resources/dark_resources/robber32.png create mode 100644 assets/resources/dark_resources/subtract_btn32.png create mode 100644 assets/resources/pattern32.png create mode 100644 assets/resources/robber32.png create mode 100644 assets/resources/subtract_btn32.png diff --git a/CHANGELOG.md b/CHANGELOG.md index c97109b1..6d183147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ CHANGELOG for FlatCAM beta ================================================= +29.10.2020 + +- added icons in most application Tools +- updated Punch Gerber Tool such that the aperture table is updated upon clicking of the checboxes in Processed Pads Type + 28.10.2020 - a series of PEP8 corrections in the FlatCAMGeometry.py diff --git a/appTools/ToolCopperThieving.py b/appTools/ToolCopperThieving.py index dc97793d..7a72c521 100644 --- a/appTools/ToolCopperThieving.py +++ b/appTools/ToolCopperThieving.py @@ -1420,6 +1420,7 @@ class ThievingUI: # ## Insert Copper Thieving self.fill_button = QtWidgets.QPushButton(_("Insert Copper thieving")) + self.fill_button.setIcon(QtGui.QIcon(self.app.resource_location + '/copperfill32.png')) self.fill_button.setToolTip( _("Will add a polygon (may be split in multiple parts)\n" "that will surround the actual Gerber traces at a certain distance.") @@ -1481,6 +1482,7 @@ class ThievingUI: # ## Insert Robber Bar self.rb_button = QtWidgets.QPushButton(_("Insert Robber Bar")) + self.rb_button.setIcon(QtGui.QIcon(self.app.resource_location + '/robber32.png')) self.rb_button.setToolTip( _("Will add a polygon with a defined thickness\n" "that will surround the actual Gerber object\n" @@ -1560,6 +1562,7 @@ class ThievingUI: # ## Pattern Plating Mask self.ppm_button = QtWidgets.QPushButton(_("Generate pattern plating mask")) + self.ppm_button.setIcon(QtGui.QIcon(self.app.resource_location + '/pattern32.png')) self.ppm_button.setToolTip( _("Will add to the soldermask gerber geometry\n" "the geometries of the copper thieving and/or\n" diff --git a/appTools/ToolCorners.py b/appTools/ToolCorners.py index 713833f0..2786eea5 100644 --- a/appTools/ToolCorners.py +++ b/appTools/ToolCorners.py @@ -428,6 +428,7 @@ class CornersUI: # ## Insert Corner Marker self.add_marker_button = FCButton(_("Add Marker")) + self.add_marker_button.setIcon(QtGui.QIcon(self.app.resource_location + '/corners_32.png')) self.add_marker_button.setToolTip( _("Will add corner markers to the selected Gerber file.") ) diff --git a/appTools/ToolDblSided.py b/appTools/ToolDblSided.py index 100db07d..ba8f51c0 100644 --- a/appTools/ToolDblSided.py +++ b/appTools/ToolDblSided.py @@ -785,6 +785,7 @@ class DsidedUI: grid_lay3.addWidget(self.box_combo, 3, 0, 1, 2) self.mirror_button = QtWidgets.QPushButton(_("Mirror")) + self.mirror_button.setIcon(QtGui.QIcon(self.app.resource_location + '/doubleside16.png')) self.mirror_button.setToolTip( _("Mirrors (flips) the specified object around \n" "the specified axis. Does not create a new \n" @@ -921,6 +922,7 @@ class DsidedUI: # ## Buttons self.create_alignment_hole_button = QtWidgets.QPushButton(_("Create Excellon Object")) + self.create_alignment_hole_button.setIcon(QtGui.QIcon(self.app.resource_location + '/drill32.png')) self.create_alignment_hole_button.setToolTip( _("Creates an Excellon Object containing the\n" "specified alignment holes and their mirror\n" diff --git a/appTools/ToolEtchCompensation.py b/appTools/ToolEtchCompensation.py index 08f10203..dae10b05 100644 --- a/appTools/ToolEtchCompensation.py +++ b/appTools/ToolEtchCompensation.py @@ -441,6 +441,7 @@ class EtchUI: grid0.addWidget(separator_line, 22, 0, 1, 2) self.compensate_btn = FCButton(_('Compensate')) + self.compensate_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/etch_32.png')) self.compensate_btn.setToolTip( _("Will increase the copper features thickness to compensate the lateral etch.") ) diff --git a/appTools/ToolExtractDrills.py b/appTools/ToolExtractDrills.py index 3bb4ab71..5b88ec28 100644 --- a/appTools/ToolExtractDrills.py +++ b/appTools/ToolExtractDrills.py @@ -686,6 +686,7 @@ class ExtractDrillsUI: # Extract drills from Gerber apertures flashes (pads) self.e_drills_button = QtWidgets.QPushButton(_("Extract Drills")) + self.e_drills_button.setIcon(QtGui.QIcon(self.app.resource_location + '/drill16.png')) self.e_drills_button.setToolTip( _("Extract drills from a given Gerber file.") ) diff --git a/appTools/ToolFiducials.py b/appTools/ToolFiducials.py index 876f8284..1a763223 100644 --- a/appTools/ToolFiducials.py +++ b/appTools/ToolFiducials.py @@ -882,6 +882,7 @@ class FidoUI: # ## Insert Copper Fiducial self.add_cfid_button = QtWidgets.QPushButton(_("Add Fiducial")) + self.add_cfid_button.setIcon(QtGui.QIcon(self.app.resource_location + '/fiducials_32.png')) self.add_cfid_button.setToolTip( _("Will add a polygon on the copper layer to serve as fiducial.") ) diff --git a/appTools/ToolInvertGerber.py b/appTools/ToolInvertGerber.py index 59270e9f..3f6f6ec0 100644 --- a/appTools/ToolInvertGerber.py +++ b/appTools/ToolInvertGerber.py @@ -267,6 +267,7 @@ class InvertUI: grid0.addWidget(separator_line, 9, 0, 1, 2) self.invert_btn = FCButton(_('Invert Gerber')) + self.invert_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/invert32.png')) self.invert_btn.setToolTip( _("Will invert the Gerber object: areas that have copper\n" "will be empty of copper and previous empty area will be\n" diff --git a/appTools/ToolOptimal.py b/appTools/ToolOptimal.py index 6e73af83..9cac2356 100644 --- a/appTools/ToolOptimal.py +++ b/appTools/ToolOptimal.py @@ -573,6 +573,7 @@ class OptimalUI: # GO button self.calculate_button = FCButton(_("Find Minimum")) + self.calculate_button.setIcon(QtGui.QIcon(self.app.resource_location + '/open_excellon32.png')) self.calculate_button.setToolTip( _("Calculate the minimum distance between copper features,\n" "this will allow the determination of the right tool to\n" diff --git a/appTools/ToolPanelize.py b/appTools/ToolPanelize.py index 03864f2b..b4edd0c5 100644 --- a/appTools/ToolPanelize.py +++ b/appTools/ToolPanelize.py @@ -8,7 +8,8 @@ from PyQt5 import QtWidgets, QtGui, QtCore from appTool import AppTool -from appGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet, FCCheckBox, OptionalInputSection, FCComboBox +from appGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet, FCCheckBox, OptionalInputSection, FCComboBox, \ + FCButton, FCLabel from camlib import grace from copy import deepcopy @@ -639,7 +640,7 @@ class PanelizeUI: self.layout = layout # ## Title - title_label = QtWidgets.QLabel("%s" % self.toolName) + title_label = FCLabel("%s" % self.toolName) title_label.setStyleSheet(""" QLabel { @@ -649,7 +650,7 @@ class PanelizeUI: """) self.layout.addWidget(title_label) - self.object_label = QtWidgets.QLabel('%s:' % _("Source Object")) + self.object_label = FCLabel('%s:' % _("Source Object")) self.object_label.setToolTip( _("Specify the type of object to be panelized\n" "It can be of type: Gerber, Excellon or Geometry.\n" @@ -673,7 +674,7 @@ class PanelizeUI: self.type_obj_combo.setItemIcon(1, QtGui.QIcon(self.app.resource_location + "/drill16.png")) self.type_obj_combo.setItemIcon(2, QtGui.QIcon(self.app.resource_location + "/geometry16.png")) - self.type_object_label = QtWidgets.QLabel('%s:' % _("Object Type")) + self.type_object_label = FCLabel('%s:' % _("Object Type")) form_layout_0.addRow(self.type_object_label, self.type_obj_combo) @@ -696,7 +697,7 @@ class PanelizeUI: # Type of box Panel object self.reference_radio = RadioSet([{'label': _('Object'), 'value': 'object'}, {'label': _('Bounding Box'), 'value': 'bbox'}]) - self.box_label = QtWidgets.QLabel("%s:" % _("Penelization Reference")) + self.box_label = FCLabel("%s:" % _("Penelization Reference")) self.box_label.setToolTip( _("Choose the reference for panelization:\n" "- Object = the bounding box of a different object\n" @@ -719,7 +720,7 @@ class PanelizeUI: self.type_box_combo.setItemIcon(0, QtGui.QIcon(self.app.resource_location + "/flatcam_icon16.png")) self.type_box_combo.setItemIcon(1, QtGui.QIcon(self.app.resource_location + "/geometry16.png")) - self.type_box_combo_label = QtWidgets.QLabel('%s:' % _("Box Type")) + self.type_box_combo_label = FCLabel('%s:' % _("Box Type")) self.type_box_combo_label.setToolTip( _("Specify the type of object to be used as an container for\n" "panelization. It can be: Gerber or Geometry type.\n" @@ -745,7 +746,7 @@ class PanelizeUI: separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) form_layout.addRow(separator_line) - panel_data_label = QtWidgets.QLabel("%s:" % _("Panel Data")) + panel_data_label = FCLabel("%s:" % _("Panel Data")) panel_data_label.setToolTip( _("This informations will shape the resulting panel.\n" "The number of rows and columns will set how many\n" @@ -761,7 +762,7 @@ class PanelizeUI: self.spacing_columns.set_range(0, 9999) self.spacing_columns.set_precision(4) - self.spacing_columns_label = QtWidgets.QLabel('%s:' % _("Spacing cols")) + self.spacing_columns_label = FCLabel('%s:' % _("Spacing cols")) self.spacing_columns_label.setToolTip( _("Spacing between columns of the desired panel.\n" "In current units.") @@ -773,7 +774,7 @@ class PanelizeUI: self.spacing_rows.set_range(0, 9999) self.spacing_rows.set_precision(4) - self.spacing_rows_label = QtWidgets.QLabel('%s:' % _("Spacing rows")) + self.spacing_rows_label = FCLabel('%s:' % _("Spacing rows")) self.spacing_rows_label.setToolTip( _("Spacing between rows of the desired panel.\n" "In current units.") @@ -784,7 +785,7 @@ class PanelizeUI: self.columns = FCSpinner(callback=self.confirmation_message_int) self.columns.set_range(0, 9999) - self.columns_label = QtWidgets.QLabel('%s:' % _("Columns")) + self.columns_label = FCLabel('%s:' % _("Columns")) self.columns_label.setToolTip( _("Number of columns of the desired panel") ) @@ -794,7 +795,7 @@ class PanelizeUI: self.rows = FCSpinner(callback=self.confirmation_message_int) self.rows.set_range(0, 9999) - self.rows_label = QtWidgets.QLabel('%s:' % _("Rows")) + self.rows_label = FCLabel('%s:' % _("Rows")) self.rows_label.setToolTip( _("Number of rows of the desired panel") ) @@ -808,7 +809,7 @@ class PanelizeUI: # Type of resulting Panel object self.panel_type_radio = RadioSet([{'label': _('Gerber'), 'value': 'gerber'}, {'label': _('Geo'), 'value': 'geometry'}]) - self.panel_type_label = QtWidgets.QLabel("%s:" % _("Panel Type")) + self.panel_type_label = FCLabel("%s:" % _("Panel Type")) self.panel_type_label.setToolTip( _("Choose the type of object for the panel object:\n" "- Geometry\n" @@ -842,7 +843,7 @@ class PanelizeUI: self.x_width_entry.set_precision(4) self.x_width_entry.set_range(0, 9999) - self.x_width_lbl = QtWidgets.QLabel('%s:' % _("Width (DX)")) + self.x_width_lbl = FCLabel('%s:' % _("Width (DX)")) self.x_width_lbl.setToolTip( _("The width (DX) within which the panel must fit.\n" "In current units.") @@ -853,7 +854,7 @@ class PanelizeUI: self.y_height_entry.set_range(0, 9999) self.y_height_entry.set_precision(4) - self.y_height_lbl = QtWidgets.QLabel('%s:' % _("Height (DY)")) + self.y_height_lbl = FCLabel('%s:' % _("Height (DY)")) self.y_height_lbl.setToolTip( _("The height (DY)within which the panel must fit.\n" "In current units.") @@ -869,7 +870,8 @@ class PanelizeUI: form_layout.addRow(separator_line) # Buttons - self.panelize_object_button = QtWidgets.QPushButton(_("Panelize Object")) + self.panelize_object_button = FCButton(_("Panelize Object")) + self.panelize_object_button.setIcon(QtGui.QIcon(self.app.resource_location + '/panelize16.png')) self.panelize_object_button.setToolTip( _("Panelize the specified object around the specified box.\n" "In other words it creates multiple copies of the source object,\n" @@ -886,7 +888,7 @@ class PanelizeUI: self.layout.addStretch() # ## Reset Tool - self.reset_button = QtWidgets.QPushButton(_("Reset Tool")) + self.reset_button = FCButton(_("Reset Tool")) self.reset_button.setIcon(QtGui.QIcon(self.app.resource_location + '/reset32.png')) self.reset_button.setToolTip( _("Will reset the tool parameters.") diff --git a/appTools/ToolPunchGerber.py b/appTools/ToolPunchGerber.py index eab09f7b..4f8181b2 100644 --- a/appTools/ToolPunchGerber.py +++ b/appTools/ToolPunchGerber.py @@ -74,6 +74,12 @@ class ToolPunchGerber(AppTool): self.ui.other_ring_entry.setDisabled(False) if state else self.ui.other_ring_entry.setDisabled(True) ) + self.ui.circular_cb.stateChanged.connect(self.build_tool_ui) + self.ui.oblong_cb.stateChanged.connect(self.build_tool_ui) + self.ui.square_cb.stateChanged.connect(self.build_tool_ui) + self.ui.rectangular_cb.stateChanged.connect(self.build_tool_ui) + self.ui.other_cb.stateChanged.connect(self.build_tool_ui) + def run(self, toggle=True): self.app.defaults.report_usage("ToolPunchGerber()") @@ -131,6 +137,10 @@ class ToolPunchGerber(AppTool): self.ui.factor_entry.set_value(float(self.app.defaults["tools_punch_hole_prop_factor"])) def build_tool_ui(self): + # reset table + self.ui.apertures_table.clear() + self.ui.apertures_table.setRowCount(0) + # get the Gerber file who is the source of the punched Gerber selection_index = self.ui.gerber_object_combo.currentIndex() model_index = self.app.collection.index(selection_index, 0, self.ui.gerber_object_combo.rootModelIndex()) @@ -144,17 +154,54 @@ class ToolPunchGerber(AppTool): # no object loaded sorted_apertures = [] - n = len(sorted_apertures) + # n = len(sorted_apertures) + # calculate how many rows to add + n = 0 + for ap_code in sorted_apertures: + ap_code = str(ap_code) + ap_type = obj.apertures[ap_code]['type'] + + if ap_type == 'C' and self.ui.circular_cb.get_value() is True: + n += 1 + if ap_type == 'R': + if self.ui.square_cb.get_value() is True: + n += 1 + elif self.ui.rectangular_cb.get_value() is True: + n += 1 + if ap_type == 'O' and self.ui.oblong_cb.get_value() is True: + n += 1 + if ap_type not in ['C', 'R', 'O'] and self.ui.other_cb.get_value() is True: + n += 1 + self.ui.apertures_table.setRowCount(n) row = 0 for ap_code in sorted_apertures: ap_code = str(ap_code) + ap_type = obj.apertures[ap_code]['type'] + if ap_type == 'C': + if self.ui.circular_cb.get_value() is False: + continue + elif ap_type == 'R': + if self.ui.square_cb.get_value() is True: + pass + elif self.ui.rectangular_cb.get_value() is True: + pass + else: + continue + elif ap_type == 'O': + if self.ui.oblong_cb.get_value() is False: + continue + elif self.ui.other_cb.get_value() is True: + pass + else: + continue + ap_code_item = QtWidgets.QTableWidgetItem(ap_code) ap_code_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - ap_type_item = QtWidgets.QTableWidgetItem(str(obj.apertures[ap_code]['type'])) + ap_type_item = QtWidgets.QTableWidgetItem(str(ap_type)) ap_type_item.setFlags(QtCore.Qt.ItemIsEnabled) try: @@ -174,6 +221,7 @@ class ToolPunchGerber(AppTool): # increment row row += 1 + self.ui.apertures_table.selectColumn(0) self.ui.apertures_table.resizeColumnsToContents() self.ui.apertures_table.resizeRowsToContents() @@ -932,8 +980,8 @@ class PunchUI: [ {'label': _('Excellon'), 'value': 'exc'}, {'label': _("Fixed Diameter"), 'value': 'fixed'}, - {'label': _("Fixed Annular Ring"), 'value': 'ring'}, - {'label': _("Proportional"), 'value': 'prop'} + {'label': _("Proportional"), 'value': 'prop'}, + {'label': _("Fixed Annular Ring"), 'value': 'ring'} ], orientation='vertical', stretch=False) @@ -1094,6 +1142,7 @@ class PunchUI: # Buttons self.punch_object_button = QtWidgets.QPushButton(_("Punch Gerber")) + self.punch_object_button.setIcon(QtGui.QIcon(self.app.resource_location + '/punch32.png')) self.punch_object_button.setToolTip( _("Create a Gerber object from the selected object, within\n" "the specified box.") diff --git a/appTools/ToolQRCode.py b/appTools/ToolQRCode.py index d92e4028..29398b01 100644 --- a/appTools/ToolQRCode.py +++ b/appTools/ToolQRCode.py @@ -892,6 +892,7 @@ class QRcodeUI: # ## Insert QRCode self.qrcode_button = QtWidgets.QPushButton(_("Insert QRCode")) + self.qrcode_button.setIcon(QtGui.QIcon(self.app.resource_location + '/qrcode32.png')) self.qrcode_button.setToolTip( _("Create the QRCode object.") ) diff --git a/appTools/ToolRulesCheck.py b/appTools/ToolRulesCheck.py index f5e26bee..b48882c1 100644 --- a/appTools/ToolRulesCheck.py +++ b/appTools/ToolRulesCheck.py @@ -1601,6 +1601,7 @@ class RulesUI: # hlay_2.addStretch() self.run_button = FCButton(_("Run Rules Check")) + self.run_button.setIcon(QtGui.QIcon(self.app.resource_location + '/rules32.png')) self.run_button.setToolTip( _("Panelize the specified object around the specified box.\n" "In other words it creates multiple copies of the source object,\n" diff --git a/appTools/ToolSub.py b/appTools/ToolSub.py index ea45fd14..c593e5c3 100644 --- a/appTools/ToolSub.py +++ b/appTools/ToolSub.py @@ -704,6 +704,7 @@ class SubUI: grid0.addWidget(self.sub_gerber_combo, 4, 1) self.intersect_btn = FCButton(_('Subtract Gerber')) + self.intersect_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/subtract_btn32.png')) self.intersect_btn.setToolTip( _("Will remove the area occupied by the subtractor\n" "Gerber from the Target Gerber.\n" @@ -761,6 +762,7 @@ class SubUI: grid0.addWidget(self.close_paths_cb, 16, 0, 1, 2) self.intersect_geo_btn = FCButton(_('Subtract Geometry')) + self.intersect_geo_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/subtract_btn32.png')) self.intersect_geo_btn.setToolTip( _("Will remove the area occupied by the subtractor\n" "Geometry from the Target Geometry.") diff --git a/assets/resources/dark_resources/pattern32.png b/assets/resources/dark_resources/pattern32.png new file mode 100644 index 0000000000000000000000000000000000000000..2559300513ce0a2aed24781d6ef8e13e05ee45c6 GIT binary patch literal 1608 zcmZ`(eLNF*82?RUl^cDMm(;j&xYBlOLgu~5yvG&-eN3xlX{l!#5jl1^~c4aIXF; z{C2%ILREd3_99IM&}bJQ7XT`AG*?LK>tY1X-v@vcGXR(w04%8}<|F_~XaGJD0l?-1 zpr3eO;AgKA)WW^oT>*HSWr9&nn-X!yX#i;bwq6jnh1L!g38Q=XxWS~Gcj}|IN2ltS z1E8+w;p%b}C(2?|;@IQc+tNO#u5BY<*2AA%YD_{7g%dn8c6ar>IU~)v!D3k$(uZ&2 zUI=sZuXTK|frme`%&jfDCEUjfySb|gmSGyV)~x=n6P}AXYvLfQf2*vQ@gieKXx+>5 zR*1#6tih`mgR>KtZY`&b&A&>hF>BKYr>B6Ko?8B1Sx7nceJgSM!fpAiF$*=rou__` z_{<*qOcRkGME9@uatg7u$cD7>{RKA^%2!_+cT?eh2-@SAuU-^EzkdVzp1WCOt+|18 zgpl9|2QN1{X9bZ1tO93|2rnb?k#(kz4D}8X;Gp z>CMEh@zlRN9@V_5L&|;n`+|byx}(VJ0|JRsKN}kMTZ+N!OrdforYxA__4G32-Z@HM zrbL73omyL1ZX35Jt$=QNurY3mta(B+!fNfXaLwkQ{iMnPT zi}a57_#G0J#54LbaA#jeS8r%)*uz4Rg2YeN4m75kPXFrou*zP#7N1?$)jdAPzBG|7 zrcL87*vXClgnir~R7^OJqQMEZEpuQf0raUC2`$BRtoFOIM57wlmmBU!2c>HdV{JB? z==N$uem^3!d)xSSQ8JA=CefZKzx>CFKdyqbM=JPWbC|G$zX25!)-U6F*;#RQ8JsqS zfJo3;DhnyzU*{n2P3x?>%P6R940xP9iKxO+IP>whLkFT`rBsV86&laW0Z+}jAyQ$# zG0)ccOMLC(PaKM%$+X3Bra6#(qDdICfjI@8$y4i5gg0&7DybHyT+7?0cc}9HK+Cyf z2Vk!mL;CFZ;mbdp@mlO3mCd+|OZUJtFD?~cimzi2OncWIk&{WRi@vZ{Jw(q~Yt-_U z?#wPGYl;ElHPAaii_-F!kq|ZSuQ>I5ywxFWaVRcGY}es*>$9-w{3+;63B=RUxtC_N z;IW%2_M9PKFupM6MxZ8q^Sb)(9jjPDCu)3vTpjaH>&#=W(s`(aH4#M0xq05YucB%$ zY2--`odCy{YOlvSw)547rxXs7trMigSECw4V`xtxQzDYdnARm0%@yBpn(3Jrf5HzV zC5Km^=reoxN1mj~_DAH&v9&`CL&mEtZMC=E*5TMBE7l`{;=(7r!c^O{Af z-m}Z}H?O4Oe`)@cJ{#hl`i_m_jt);XJF>~@icWs|wDoEc-!R=~-lvP{(4lni4KWPYOJ}fEF4LzaT?72n{xP>p9M39eL@0!lXWyPX zP7xU7n4a2&bAK%=o}wA0gG=l>YuDW_wi&i}sw zKOeKAGHhQ@2%tpKlS$M_ker;1ib){TB1nmmC<-;2Gi`6ES^^$!c-M+U#PojwLkIGE literal 0 HcmV?d00001 diff --git a/assets/resources/dark_resources/robber32.png b/assets/resources/dark_resources/robber32.png new file mode 100644 index 0000000000000000000000000000000000000000..e647291541fcadf9f54ae26c3a0c8296d2b4aaf5 GIT binary patch literal 1172 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-GzZ+Rj;xUkjGiz z5n0T@z;^_M8K-LVNdpDhOFVsD*`IL9i0er2b`}BJz?|gi;uzv_d~IlMPKc|B?f18N zFK11=HSO*#{<~~R7bQ#;J2V&NiW*#OFs*C3@qu0FO2@G<;ra!Ri`|khxNrn=b}ft2 zVaxLE*=XP6u&8rlKU(A`EH|<|o z;Qq*ie)Aqpy4m@Z;lNUzCz5j8elI$0yVJMlc$oir-|Zjm{+-FS=z0I}^4l5jb!IcQ zlv%#M^DW|S4-l7f#m}UA@{yf`xaW6~4QryK?uP#_{F)*8`|RYG_ck|s zZkyS=G3wgq5k?T`Kxmg?lX@qVpB^nw1C=*|}PBH6kPYj+&mzDdJ!oMgjJJHawg1XS zTZyBQUp(hWtNMC8%*r_ME>S-E&D^q?wR8T~OyB>VoiV{6=l(N+?Yue+KX~QO+A?%% zuVi2-X1`t0ayKVkHu_Av!=4lS4zZLUU3KZgjjVr%X6Y1JzFs+LZPu<7{|x>4Zjq8ir7g;+_*KEeX+N9tHVR)+ zIQ4N#@LRRNGZpG>{lX#`SWi?&9C6jJvYjVYntJWO-^j+yB}3>}Rx)Z?gS0cgAI422?F^jVMV;EJ?LWE=mPb3`Pb<2D*j@x<(cuM#feq zCRRq~+6D$z1_o;m2!x<$$jwj5OsmAL;qKfOz>~}U&Kt&9mu6{1-oD!Mk4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-GzZ+Rj;xUkjGiz z5n0T@z;^_M8K-LVNdpDhOFVsD*`IL9hzpqnh8rmYH6?nwIEHu}pF8!ucSxYfar=A$ zUw7jbS3H;M#Hwm6VRO`5b3|!FXh8Qrj_|E7#a-AgnyuRVJ5r?U*&@d-Bd_wM8d=8Y z_Pm!qeZ@oBpSw6`#`MpR*Sxd-UbFA{oa*}`a0_)X@w&cY?Oyt;>hQ_Cn$@wTuihK5g|IQqxniF=`{pGpYe7B- z!TXjD9Y=NJy==v~8Ba5&HO%2JjM6PlFlJP1IOoK&MtDvq!(xYgMW!!Jd+*qt%KdpM zuH8rbqr!r8qjHUS#@-WOSQxekN^eRjx7$%2w`~5$wzuc&W+t8774tD=?<1r4aih{XlpmYf74gyjoXgf{slR@FEx2}c_0`)w-l7RBBR?DI?y`-n>OXBV-R7O~ z%oX2`r5N#6zumXf+C*uxrqKFZAD7wY2CGipKG&|RG4qh$k$nQpe3qrxJoS$^@IHU| z&-&c4dKLyDcjoImyY3gQGy1T5f126dmp@n@O)Eb5a?#YbE1&-zbTf~?vL^M|KgOlO zW_kP~Q}co8PqoA~q9i4;B-JXpC>2OC7#SED=o%X68d-!G8Cw}zSeY7W8yHv_7|ag? zrFkR`x%nxXX_dG&yyHGJ3#dU7WJ7R%T1k0gQ7S`udAVL@UUqSEVnM22eo^}DcQ#T$ OMGT&k4UEa{HEjtmSN`?>!lvVtU&J%W50 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