diff --git a/Scripts/TypeRig GUI/Panel/NNode.py b/Scripts/TypeRig GUI/Panel/NNode.py index 57d8102..00d36b2 100644 --- a/Scripts/TypeRig GUI/Panel/NNode.py +++ b/Scripts/TypeRig GUI/Panel/NNode.py @@ -14,6 +14,9 @@ import fontlab as fl6 from PythonQt import QtCore, QtGui +from typerig.proxy.fl.objects.font import pFont +from typerig.proxy.fl.objects.glyph import eGlyph + from typerig.proxy.fl.actions.node import TRNodeActionCollector from typerig.proxy.fl.application.app import pWorkspace #from typerig.proxy.fl.gui import QtGui @@ -25,7 +28,7 @@ global pMode pLayers = None pMode = 0 -app_name, app_version = 'TypeRig | Nodes', '3.00' +app_name, app_version = 'TypeRig | Nodes', '3.01' TRToolFont = getTRIconFontPath() font_loaded = QtGui.QFontDatabase.addApplicationFont(TRToolFont) @@ -71,6 +74,14 @@ color: #ffffff; } +QPushButton#btn_panel:checked:hover { + background-color: #9c9e9f; + border: 1px solid #dadbdc; + border-top-color: #d1d2d3; + color: #ffffff; + +} + QPushButton#btn_panel:hover { background-color: #ffffff; color: #212121; @@ -98,6 +109,7 @@ def __init__(self): super(TRNodeBasics, self).__init__() # - Init + self.ext_target = {} # - Layout self.lay_main = QtGui.QVBoxLayout() @@ -145,7 +157,6 @@ def __init__(self): lay_corner = QtGui.QGridLayout() lay_corner.setContentsMargins(0, 0, 0, 0) - tooltip_button = 'Corner Mitre' self.btn_corner_mitre = CustomSpinButton('corner_mitre', (0., 300., 0., 1.), ('Set value', tooltip_button), ('spn_panel', 'btn_panel')) lay_corner.addWidget(self.btn_corner_mitre, 1, 0, 1, 3) @@ -175,14 +186,194 @@ def __init__(self): self.btn_node_round = CustomPushButton('node_round', tooltip=tooltip_button, obj_name='btn_panel') lay_corner.addWidget(self.btn_node_round, 2, 5, 0, 1) self.btn_node_round.clicked.connect(lambda: TRNodeActionCollector.node_round(pMode, pLayers, get_modifier(QtCore.Qt.AltModifier), get_modifier(QtCore.Qt.ShiftModifier))) - box_corner.setLayout(lay_corner) self.lay_main.addWidget(box_corner) + # -- Align Tools + box_align = QtGui.QGroupBox() + box_align.setObjectName('box_group') + + self.grp_align_options_shift = QtGui.QButtonGroup() + self.grp_align_options_other = QtGui.QButtonGroup() + self.grp_align_actions = QtGui.QButtonGroup() + + lay_align = QtGui.QGridLayout() + lay_align.setContentsMargins(0, 0, 0, 0) + + tooltip_button = "Smart Shift: Shift oncurve nodes together with their respective offcurve nodes even when they are not explicitly selected," + self.chk_shift_smart = CustomPushButton("shift_smart", checkable=True, cheked=False, tooltip=tooltip_button, obj_name='btn_panel') + self.grp_align_options_shift.addButton(self.chk_shift_smart, 1) + lay_align.addWidget(self.chk_shift_smart, 0, 0) + + tooltip_button = "Simple Shift: Shift only selected nodes." + self.chk_shift_dumb = CustomPushButton("shift_dumb", checkable=True, cheked=True, tooltip=tooltip_button, obj_name='btn_panel') + self.grp_align_options_shift.addButton(self.chk_shift_dumb, 2) + lay_align.addWidget(self.chk_shift_dumb, 0, 1) + + tooltip_button = "Keep relations between selected nodes" + self.chk_shift_keep_dimension = CustomPushButton("shift_keep_dimension", checkable=True, cheked=False, tooltip=tooltip_button, obj_name='btn_panel') + self.grp_align_options_other.addButton(self.chk_shift_keep_dimension, 1) + lay_align.addWidget(self.chk_shift_keep_dimension, 0, 2) + + tooltip_button = "Intercept vertical position" + self.chk_shift_intercept = CustomPushButton("shift_intercept", checkable=True, cheked=False, tooltip=tooltip_button, obj_name='btn_panel') + self.grp_align_options_other.addButton(self.chk_shift_intercept, 2) + lay_align.addWidget(self.chk_shift_intercept, 0, 3) + + tooltip_button = "Pick target node for alignment" + self.chk_node_target = CustomPushButton("node_target", checkable=True, cheked=False, tooltip=tooltip_button, obj_name='btn_panel') + self.chk_node_target.clicked.connect(self.target_set) + self.grp_align_options_other.addButton(self.chk_node_target, 3) + lay_align.addWidget(self.chk_node_target, 0, 4) + + # - Actions + tooltip_button = "Align selected nodes left" + self.btn_node_align_left = CustomPushButton("node_align_left", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_left.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'L', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_left) + lay_align.addWidget(self.btn_node_align_left, 1, 0) + + tooltip_button = "Align selected nodes right" + self.btn_node_align_right = CustomPushButton("node_align_right", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_right.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'R', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_right) + lay_align.addWidget(self.btn_node_align_right, 1, 1) + + tooltip_button = "Align selected nodes top" + self.btn_node_align_top = CustomPushButton("node_align_top", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_top.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'T', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_top) + lay_align.addWidget(self.btn_node_align_top, 1, 2) + + tooltip_button = "Align selected nodes bottom" + self.btn_node_align_bottom = CustomPushButton("node_align_bottom", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_bottom.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'B', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_bottom) + lay_align.addWidget(self.btn_node_align_bottom, 1, 3) + + tooltip_button = "Collapse all selected nodes to target" + self.btn_node_target_collapse = CustomPushButton("node_target_collapse", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_target_collapse.clicked.connect(self.target_collapse) + self.grp_align_actions.addButton(self.btn_node_target_collapse) + lay_align.addWidget(self.btn_node_target_collapse, 1, 4) + + tooltip_button = "Align selected nodes to horizontal center of selection" + self.btn_node_align_selection_x = CustomPushButton("node_align_selection_x", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_selection_x.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'C', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_selection_x) + lay_align.addWidget(self.btn_node_align_selection_x, 2, 0) + + tooltip_button = "Align selected nodes to vertical center of selection" + self.btn_node_align_selection_y = CustomPushButton("node_align_selection_y", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_selection_y.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'E', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_selection_y) + lay_align.addWidget(self.btn_node_align_selection_y, 2, 1) + + tooltip_button = "Align selected nodes to the horizontal middle of outline bounding box." + self.btn_node_align_outline_x = CustomPushButton("node_align_outline_x", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_outline_x.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'BBoxCenterX', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_outline_x) + lay_align.addWidget(self.btn_node_align_outline_x, 2, 2) + + tooltip_button = "Align selected nodes to the vertical middle of outline bounding box." + self.btn_node_align_outline_y = CustomPushButton("node_align_outline_y", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_outline_y.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'BBoxCenterY', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_outline_y) + lay_align.addWidget(self.btn_node_align_outline_y, 2, 3) + + tooltip_button = "Align selected nodes to Measurment line" + self.btn_node_dimension_guide = CustomPushButton("dimension_guide", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_dimension_guide.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'FontMetrics_5', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_dimension_guide) + lay_align.addWidget(self.btn_node_dimension_guide, 2, 4) + + tooltip_button = "Align selected node in the horizontal middle of its direct neighbors" + self.btn_node_align_neigh_x = CustomPushButton("node_align_neigh_x", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_neigh_x.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'peerCenterX', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_neigh_x) + lay_align.addWidget(self.btn_node_align_neigh_x, 3, 0) + + tooltip_button = "Align selected node in the vertical middle of its direct neighbors" + self.btn_node_align_neigh_y = CustomPushButton("node_align_neigh_y", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_neigh_y.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'peerCenterY', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_neigh_y) + lay_align.addWidget(self.btn_node_align_neigh_y, 3, 1) + + tooltip_button = "Align selected nodes to an imaginary line runnig between highest and lowest node in selection" + self.btn_node_align_min_max_Y = CustomPushButton("node_align_min_max_Y", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_min_max_Y.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'Y', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_min_max_Y) + lay_align.addWidget(self.btn_node_align_min_max_Y, 3, 2) + + tooltip_button = "Align selected nodes to an imaginary line runnig between lowest and highest node in selection" + self.btn_node_align_min_max_X = CustomPushButton("node_align_min_max_X", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_align_min_max_X.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'X', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_align_min_max_X) + lay_align.addWidget(self.btn_node_align_min_max_X, 3, 3) + + tooltip_button = "Align selected nodes to Font metrics: Ascender height" + self.btn_node_dimension_ascender = CustomPushButton("dimension_ascender", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_dimension_ascender.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'FontMetrics_0', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_dimension_ascender) + lay_align.addWidget(self.btn_node_dimension_ascender, 5, 0) + + tooltip_button = "Align selected nodes to Font metrics: Caps height" + self.btn_node_dimension_caps = CustomPushButton("dimension_caps", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_dimension_caps.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'FontMetrics_1', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_dimension_caps) + lay_align.addWidget(self.btn_node_dimension_caps, 5, 1) + + tooltip_button = "Align selected nodes to Font metrics: X height" + self.btn_node_dimension_xheight = CustomPushButton("dimension_xheight", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_dimension_xheight.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'FontMetrics_3', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_dimension_xheight) + lay_align.addWidget(self.btn_node_dimension_xheight, 5, 2) + + tooltip_button = "Align selected nodes to Font metrics: Baseline" + self.btn_node_dimension_baseline = CustomPushButton("dimension_baseline", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_dimension_baseline.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'FontMetrics_4', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_dimension_baseline) + lay_align.addWidget(self.btn_node_dimension_baseline, 5, 3) + + tooltip_button = "Align selected nodes to Font metrics: Descender" + self.btn_node_dimension_descender = CustomPushButton("dimension_descender", tooltip=tooltip_button, obj_name='btn_panel') + self.btn_node_dimension_descender.clicked.connect(lambda: TRNodeActionCollector.nodes_align(pMode, pLayers, 'FontMetrics_2', self.chk_shift_intercept.isChecked(), self.chk_shift_keep_dimension.isChecked(), self.chk_shift_smart.isChecked(), self.ext_target)) + self.grp_align_actions.addButton(self.btn_node_dimension_descender) + lay_align.addWidget(self.btn_node_dimension_descender, 5, 4) + + box_align.setLayout(lay_align) + self.lay_main.addWidget(box_align) + # - Finish it self.setLayout(self.lay_main) + # - Procedures ------------------------------------------------ + def target_set(self): + if self.chk_node_target.isChecked(): + glyph = eGlyph() + wLayers = glyph._prepareLayers(pLayers) + + for layer in wLayers: + self.ext_target[layer] = glyph.selectedNodes(layer)[0] + + else: + self.ext_target = {} + + def target_collapse(self): + if self.chk_node_target.isChecked() and len(self.ext_target.keys()): + glyph = eGlyph() + wLayers = glyph._prepareLayers(pLayers) + + for layer in wLayers: + if layer in self.ext_target.keys(): + for node in glyph.selectedNodes(layer): + node.x = self.ext_target[layer].x + node.y = self.ext_target[layer].y + + glyph.update() + glyph.updateObject(glyph.fl, 'Glyph: {}; Nodes collapsed; Layers:\t {}'.format(glyph.name, '; '.join(wLayers))) + # - Tabs ------------------------------- class tool_tab(QtGui.QWidget):