Browse code

Core update 1.3.1 == Copyright

Hexatron authored on 13/04/2017 07:05:13
Showing 5 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,328 @@
0
+"""
1
+Hi everybody =)
2
+
3
+The common commands available via the hotbox menu concern shape's / mesh editing, but,
4
+as a rigger, as an animator, as a render guy, you don't need these tools. What about
5
+having your own :) ?
6
+
7
+I introduce you with Radial Designer, a script made to help Maya users to customize their
8
+marking menu.
9
+The Marking menu is the radial menu opening when you press the right button of the mouse
10
+in Maya's viewport, as you probably already know, this tool is crucial if you want to
11
+work fast and efficiently.
12
+
13
+Using this designer you'll be able to fastly set and edit your menus and command
14
+associated, thus you can design a menu for animation, an other for rigging, it'll
15
+help you and save a lot of time.
16
+
17
+This first stable version allows you to create / edit your raidal menu, and save it
18
+in the scene as a scriptNode. This means the next time the scene will be opened,
19
+the node will be executed asynchronously and the default Maya's menu overrided,
20
+then you just need to remove the scriptNode if you don't want your custom menu
21
+anymore.
22
+
23
+P.S : The node is named 'markingMenu_override'
24
+
25
+
26
+You can check at [http://mehdilouala.com/RadialDesigner] for a nice looking explanation of
27
+this script
28
+
29
+You can also check at [http://3dbunk.com/markingMenu] for a tutorial explaining the
30
+process step by step
31
+
32
+
33
+Upcoming release will allow you to create sub menus and load the actual overriden
34
+menu from the current scene. Also will be implemented the contextual appearing of
35
+the menu.
36
+
37
+May the peace be with you.
38
+"""
39
+
40
+__author__ = "Mehdi Louala"
41
+__copyright__ = "Copyright 2017, Mehdi Louala"
42
+__credits__ = ["Mehdi Louala"]
43
+__license__ = "GPL"
44
+__version__ = "1.3.1"
45
+__maintainer__ = "Mehdi Louala"
46
+__email__ = "mlouala@gmail.com"
47
+__status__ = "Stable Version"
48
+
49
+from functools import partial
50
+
51
+try:
52
+    from shiboken import wrapInstance as wrapinstance
53
+    from PySide.QtCore import Qt
54
+    from PySide.QtGui import QWidget, QCheckBox, QComboBox, QIcon, QLabel, QPushButton, QVBoxLayout, QTextEdit
55
+    __2017__ = False
56
+except ImportError:
57
+    from shiboken2 import wrapInstance as wrapinstance
58
+    from PySide2.QtCore import Qt
59
+    from PySide2.QtWidgets import QWidget, QCheckBox, QComboBox, QLabel, QPushButton, QVBoxLayout, QTextEdit
60
+    from PySide2.QtGui import QIcon
61
+    __2017__ = True
62
+
63
+from maya.cmds import cmdScrollFieldExecuter, columnLayout, window, deleteUI, warning, ls, delete, scriptNode, \
64
+    confirmDialog
65
+from maya.OpenMayaUI import MQtUtil
66
+from maya.mel import eval as mel_evaluate
67
+
68
+from radialDsg_rsc.widgets import Radial_View, Radial_Group, DefaultField
69
+from radialDsg_rsc.misc import getMayaWindow, __dirs__, __nice_pos__, Abstract_Menu, line, col
70
+from radialDsg_rsc.proc import MEL_proc, MEL_multiline
71
+
72
+
73
+class radialDesigner(QWidget):
74
+    def __init__(self, parent=None):
75
+        self.title = 'Radial Designer'
76
+
77
+        self.flush()
78
+
79
+        super(radialDesigner, self).__init__(parent)
80
+        self.setWindowTitle(self.title)
81
+        self.setObjectName(self.title)
82
+        self.setWindowFlags(Qt.Window)
83
+        self.setWindowIcon(QIcon(':nodeGrapherAddNodes.png'))
84
+
85
+        # Defining the UI
86
+        self.setFixedWidth(400)
87
+
88
+        L_main = QVBoxLayout(self)
89
+        L_main.setAlignment(Qt.AlignTop)
90
+        L_main.setContentsMargins(2, 4, 4, 4)
91
+        L_main.setSpacing(2)
92
+        self.setLayout(L_main)
93
+
94
+        self.C_apply_on = QComboBox(self)
95
+        self.C_apply_on.addItems(['Nurbs', 'Poly', 'Joint'])
96
+        apply_on = QLabel("Apply On : ")
97
+        apply_on.setFixedWidth(60)
98
+        L_apply_on = line(apply_on, self.C_apply_on)
99
+        L_apply_on.setContentsMargins(4, 0, 0, 0)
100
+        L_main.addLayout(L_apply_on)
101
+
102
+        # The radial viewport
103
+        self.view = Radial_View(self)
104
+        self.view.selectionChanged.connect(self.display_box)
105
+        L_main.addWidget(self.view)
106
+
107
+        def flip(target, state):
108
+            if target.isChecked() and state:
109
+                target.setChecked(False)
110
+
111
+        # we create a new Radial Group and an abstract menu associated
112
+        self.edit_boxes = {}
113
+        for pos in __dirs__:
114
+            box = Radial_Group(__nice_pos__[pos], self)
115
+
116
+            title = DefaultField(pos, box)
117
+            title.textChanged.connect(self.view[pos].updateText)
118
+            bold = QCheckBox('Bold')
119
+            italic = QCheckBox('Italic')
120
+            bold.stateChanged.connect(partial(flip, italic))
121
+            bold.stateChanged.connect(self.view[pos].setBold)
122
+            italic.stateChanged.connect(partial(flip, bold))
123
+            italic.stateChanged.connect(self.view[pos].setItalic)
124
+
125
+            echo = QCheckBox('Echo Command')
126
+            repeat = QCheckBox('Can Repeat Command')
127
+            repeat.setChecked(True)
128
+
129
+            combo = QComboBox(box)
130
+            combo.addItems(['Python', 'MEL'])
131
+            combo.currentIndexChanged.connect(partial(self.updateCodeWidget, pos))
132
+
133
+            L_box = QVBoxLayout()
134
+            code = self.codeWidget(parent=box)
135
+            L_box.addLayout(line('Title', line(title, bold, italic)))
136
+            L_box.addLayout(line('Type', combo))
137
+            L_box.addLayout(line(echo, repeat))
138
+            L_box.addLayout(line('Code', code))
139
+
140
+            box.setLayout(L_box)
141
+            box.setVisible(False)
142
+            L_main.addWidget(box)
143
+
144
+            self.edit_boxes[pos] = Abstract_Menu(self, title, combo, code,
145
+                                                  (bold, italic),
146
+                                                  (echo, repeat))
147
+            self.view[pos].abstract = self.edit_boxes[pos]
148
+            self.view[pos].abstract.position = pos
149
+            box.selection = self.view[pos]
150
+
151
+        # the final buttons
152
+        self.B_apply = QPushButton(QIcon(':setEdAddCmd.png'), 'Apply Radial Menu', self)
153
+        self.B_apply.clicked.connect(self.apply)
154
+
155
+        self.B_reset = QPushButton(QIcon(':removeRenderable.png'), 'Restore default', self)
156
+        self.B_reset.clicked.connect(self.mel)
157
+
158
+        self.B_script_node = QPushButton(QIcon(':setEdEditMode.png'), 'ScriptNode', self)
159
+        self.B_script_node.clicked.connect(self.scriptNode)
160
+
161
+        # tweaking a bit the stylesheet
162
+        self.B_script_node.setStyleSheet("QPushButton{background:#67905c;}")
163
+
164
+        L_main.addLayout(col(line(self.B_apply, self.B_reset), self.B_script_node))
165
+        def type_to_view(index):
166
+            self.view.setType(self.C_apply_on.itemText(index))
167
+        self.C_apply_on.currentIndexChanged.connect(type_to_view)
168
+
169
+        # updating the viewport with a default starting selection
170
+        self.display_box('N')
171
+        self.view['N'].setSelected()
172
+        self.edit_boxes['N']._title.setFocus()
173
+
174
+    # UI RELATED
175
+    def flush(self):
176
+        """
177
+        Cleaning the UI, removing all previous instances
178
+        """
179
+        wins = getMayaWindow().findChildren(QWidget, self.title) or []
180
+        for c in wins:
181
+            try:
182
+                c.close()
183
+            except RuntimeError:
184
+                continue
185
+            c.deleteLater()
186
+
187
+    def codeWidget(self, type='python', parent=None):
188
+        """
189
+        Creates a new QTextEdit of the given language type
190
+        :param   type: can be python or mel
191
+        :type    type: str
192
+        :param parent: the QWidget parent
193
+        :type  parent: QWidget
194
+        :return: the cmdScrollFieldExecuter class
195
+        :rtype: QTextEdit
196
+        """
197
+
198
+        if __2017__:
199
+            code = QTextEdit(parent)
200
+        else:
201
+            # creating a temporary window where we'll put the QTextEdit
202
+            tempwin = window()
203
+            columnLayout()
204
+
205
+            # creating a new cmdScrollFieldExecuter of the given language type
206
+            code_edit = cmdScrollFieldExecuter(sourceType=type, cco=False, sth=False)
207
+            # wrapping the instance by name
208
+            code = wrapinstance(long(MQtUtil.findControl(code_edit)), QTextEdit)
209
+
210
+            # reassigning correct parent
211
+            code.setParent(parent)
212
+            code.nativeParentWidget()
213
+
214
+            # removing old window
215
+            deleteUI(tempwin)
216
+
217
+        return code
218
+
219
+    def updateCodeWidget(self, position, index):
220
+        """
221
+        This updates the QTextEdit of the given Radial Group, killing old one
222
+        reparenting a new one, updating abstract
223
+        :param position: position name
224
+        :type position: str
225
+        :param index: wrap the Signal
226
+        """
227
+        pop = self.edit_boxes[position]
228
+        old = pop.code
229
+
230
+        # Killing the previous code widget
231
+        pop.box.findChildren(QLabel)[-1].deleteLater()
232
+        pop._code.deleteLater()
233
+
234
+        # Asking for a new one
235
+        code = self.codeWidget(parent=pop.box, type=pop.type.lower())
236
+
237
+        # new line layout containing our code widget
238
+        l = line('Code', code)
239
+        pop.box.layout().addLayout(l)
240
+
241
+        # assigning the code widget to the Radial Group
242
+        pop.setCodeWidget(code)
243
+        pop.code = old
244
+
245
+    def display_box(self, position):
246
+        """
247
+        This toggle the Radial Group to display only the wanted one
248
+        :param position: Position name
249
+        :type  position: str
250
+        """
251
+        for pos in self.edit_boxes:
252
+            if pos != position:
253
+                self.edit_boxes[pos].box.setVisible(False)
254
+
255
+        self.edit_boxes[position].box.setVisible(True)
256
+
257
+    # MAYA RELATED
258
+    def apply(self):
259
+        """
260
+        Applying the current Radial to the scene
261
+        """
262
+        try:
263
+            self.mel(**{self.C_apply_on.currentText().lower():self.view.format_items()})
264
+
265
+        except RuntimeError:
266
+            import sys
267
+            print sys.exc_info()
268
+            warning('Syntax Error occured, restoring default Marking Menu')
269
+            self.mel()
270
+
271
+    def mel(self, *args, **kwargs):
272
+        """
273
+        evaluate the MEL returned by the main procedure wrapper MEL_proc in proc.py
274
+        """
275
+        mel_evaluate(MEL_proc(*args, **kwargs))
276
+
277
+    def scriptNode(self):
278
+        """
279
+        Create a scriptNode containing the current Marking Menu, delete the previous one
280
+        if exists
281
+        """
282
+        node = 'markingMenu_override'
283
+        var_name = 'RadialDesigner_Script_INIT'
284
+
285
+        for item in self.view:
286
+            if not item.empty and item.abstract.type == 'Python':
287
+                if '"' in item.abstract.code:
288
+                    res = confirmDialog(title='Execution hazard',
289
+                                        message='The command <b>\'%s\'</b> is a Python command with " (double quotes) '
290
+                                                'inside, this may create issue while reading the scriptNode, do you '
291
+                                                'want to convert them to \' (simple quotes) ?<br>P.S : This is HIGHLY '
292
+                                                'recommended' % item.name, button=['Yes','No'],
293
+                                        defaultButton='Yes', cancelButton='No', dismissString='No' )
294
+                    if res == 'Yes':
295
+                        item.abstract.code = item.abstract.code.replace('"', '\'')
296
+
297
+        # defining the contextual menu from the self.view
298
+        script = MEL_proc(**{self.C_apply_on.currentText().lower():self.view.format_items(node_format=True)})
299
+        script = '''%s
300
+warning "Overriding Maya's Marking Menu, some of the original one features";
301
+warning "may have been disabled, remove the \\"%s\\" node to restore original";
302
+evalDeferred $%s;
303
+eval $%s;''' % (MEL_multiline(script, var_name), node, var_name, var_name)
304
+
305
+        # generating a default function for the restore
306
+        restore = '''%s
307
+warning "Restoring original Maya's Marking menu.";
308
+eval $%s''' % (MEL_multiline(MEL_proc(), var_name), var_name)
309
+
310
+        # we get rid of the previous one
311
+        if len(ls(node)):
312
+            delete(node)
313
+            warning('"%s" already exists, removing..' % node)
314
+
315
+        # beforeScript executes when file loads,
316
+        # afterScript executes when node is deleted
317
+        scriptNode(st=2, bs=script, afterScript=restore, n=node, stp='mel')
318
+
319
+        warning('scriptNode "%s" correctly created, reload the scene' % node)
320
+
321
+def displayRadialDesigner():
322
+    """
323
+    Display function
324
+    """
325
+    radialDsg_Win = radialDesigner(getMayaWindow())
326
+    radialDsg_Win.show()
327
+    return radialDsg_Win
0 328
\ No newline at end of file
1 329
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+__author__ = "Mehdi Louala"
1
+__copyright__ = "Copyright 2016, Mehdi Louala"
2
+__credits__ = ["Mehdi Louala"]
3
+__license__ = "GPL"
4
+__version__ = "1.3.0"
5
+__maintainer__ = "Mehdi Louala"
6
+__email__ = "mlouala@gmail.com"
7
+__status__ = "Stable Version"
0 8
\ No newline at end of file
1 9
new file mode 100644
... ...
@@ -0,0 +1,268 @@
0
+"""
1
+All internal tools & variables
2
+"""
3
+try:
4
+    from shiboken import wrapInstance as wrapinstance
5
+    from PySide.QtGui import QWidget, QColor, QBrush, QPen, QHBoxLayout, QLabel, QLinearGradient, QVBoxLayout
6
+    from PySide.QtCore import QPoint, Qt
7
+except ImportError:
8
+    from shiboken2 import wrapInstance as wrapinstance
9
+    from PySide2.QtGui import QColor, QBrush, QPen, QLinearGradient
10
+    from PySide2.QtWidgets import QWidget, QHBoxLayout, QLabel, QVBoxLayout
11
+    from PySide2.QtCore import QPoint, Qt
12
+
13
+from maya.OpenMayaUI import MQtUtil
14
+
15
+getMayaWindow = lambda: wrapinstance(long(MQtUtil.mainWindow()), QWidget)
16
+
17
+__dirs__ = ['W', 'NW', 'N', 'NE', 'E', 'SE', 'S', 'SW']
18
+
19
+__pos__ = {'W':  QPoint(0, 47),
20
+           'NW': QPoint(25, 23),
21
+           'N':  QPoint(100, 0),
22
+           'NE': QPoint(180, 23),
23
+           'E':  QPoint(200, 47),
24
+           'SE': QPoint(180, 72),
25
+           'S':  QPoint(100, 94),
26
+           'SW': QPoint(25, 72)}
27
+
28
+__nice_pos__ = {'W': 'West',
29
+                'NW': 'North-West',
30
+                'N': 'North',
31
+                'NE': 'North-East',
32
+                'E': 'East',
33
+                'SE': 'South-East',
34
+                'S': 'South',
35
+                'SW': 'South-West'}
36
+
37
+class Abstract_Menu(object):
38
+    """
39
+    The Abstract version of the Radial Button, used to set / get the widgets values
40
+    and return correct menuItem formatting
41
+    """
42
+    def __init__(self, parent, title, kindof, code, style, params):
43
+        super(Abstract_Menu, self).__init__()
44
+        self.parent = parent
45
+
46
+        # private
47
+        self._title = title
48
+        self._type = kindof
49
+        self._code = code
50
+        self._bold, self._italic = style
51
+        self._echo, self._repeat = params
52
+
53
+        self.box = code.parent()
54
+        self.position = 'N'
55
+
56
+    # SETTERS
57
+    @property
58
+    def title(self):
59
+        return self._title.text()
60
+
61
+    @title.setter
62
+    def title(self, text):
63
+        self._title.setText(text)
64
+
65
+    @property
66
+    def type(self):
67
+        return self._type.currentText()
68
+
69
+    @type.setter
70
+    def type(self, index):
71
+        if isinstance(index, int):
72
+            self._type.setCurrentIndex(index)
73
+        else:
74
+            self._type.setCurrentIndex(self._type.findText(index))
75
+
76
+    @property
77
+    def code(self):
78
+        return self._code.toPlainText()
79
+
80
+    @code.setter
81
+    def code(self, text):
82
+        self._code.setPlainText(text)
83
+
84
+    @property
85
+    def style(self):
86
+        return self._bold.isChecked(), self._italic.isChecked()
87
+
88
+    @style.setter
89
+    def style(self, styles):
90
+        bold, italic = styles
91
+        self._bold.setChecked(bold)
92
+        self._italic.setChecked(italic)
93
+
94
+    @property
95
+    def param(self):
96
+        return self._echo.isChecked(), self._repeat.isChecked()
97
+
98
+    @param.setter
99
+    def param(self, params):
100
+        echo, repeat = params
101
+        self._echo.setChecked(echo)
102
+        self._repeat.setChecked(repeat)
103
+
104
+    # OWN
105
+    def output(self, node=False):
106
+        """
107
+        output the current radial button's code to be understood by Maya
108
+
109
+        :param node: if we need this value to be inserted in a scriptNode
110
+        :type  node: bool
111
+
112
+        :return: the formatted item
113
+        :rtype: str
114
+        """
115
+        # we just exit the double quotes if is a MEL code
116
+        if self.type == 'MEL':
117
+            ret = self.code.replace('"', r'\"').replace('\n', '')
118
+            if node:
119
+                ret = ret.replace('\\n', r'\\\\n')
120
+            else:
121
+                ret = ret.replace('\\n', r'\\n')
122
+
123
+        # otherwise Python & node we quote eval as python and converts \n by \r\
124
+        elif node:
125
+            ret = r'python(\"%s\");' % self.code.strip('\n').replace('\n', '\\\\\\r\\\\\\')
126
+
127
+        # else only Python see above
128
+        else:
129
+            ret = r'python(\"%s\");' % self.code.strip('\n').replace('\n', '\\\\r\\\\')
130
+
131
+        # we finally extract the $item value to be interpreted correctly by MEL
132
+        return ret.replace('$item', '" + $item + "')
133
+
134
+    def setCodeWidget(self, codeWidget):
135
+        """
136
+        updates the codeWidget object
137
+        :param codeWidget: QTextEdit
138
+        """
139
+        self._code = codeWidget
140
+
141
+    def dispatch(self, node_format=False):
142
+        """
143
+        Returns the current Radial button formatted as a menuItem MEL object
144
+
145
+        :param node_format: if we insert in a scriptNode
146
+        :type  node_format: bool
147
+
148
+        :return: a menuItem version of the current Radial Button
149
+        :rtype: str
150
+        """
151
+        # creating a string with the given menuItem
152
+        s = 'menuItem -label "%s" ' % self.title
153
+        s += '-rp "%s" ' % self.position
154
+        s += '-c ("%s") ' % self.output(node_format)
155
+
156
+        # special parameters
157
+        bld, itl = self.style
158
+
159
+        if bld:
160
+            s += '-bld %i ' % bld
161
+        if itl:
162
+            s += '-itl %i ' % itl
163
+        s += '-ec %i -ecr %i ' % self.param
164
+
165
+        # final ;
166
+        return '%s;' % s
167
+
168
+
169
+class Pen(QPen):
170
+    """
171
+    Just a short hand class for the QPen can be ;
172
+        Pen(255, 255, 255, 1.0)         => RGB and WIDTH
173
+        Pen(Brush(255, 255, 255), 1.0)  => QBrush and WIDTH
174
+    """
175
+    def __init__(self, *components):
176
+        if len(components) == 4:
177
+            super(Pen, self).__init__(Brush(*components))
178
+        elif len(components) == 2:
179
+            c, w = components
180
+            if isinstance(c, QBrush):
181
+                super(Pen, self).__init__(c, w)
182
+            else:
183
+                super(Pen, self).__init__(Brush(c), w)
184
+        else:
185
+            super(Pen, self).__init__(Brush(components[0]), 1)
186
+
187
+
188
+class Brush(QBrush):
189
+    """
190
+    Just a short hand class for the QBrush can be ;
191
+        Brush(255, 255, 255)        => R, G and B
192
+        Brush(255)                  => RGB same component
193
+
194
+    """
195
+    def __init__(self, *components):
196
+        if len(components) == 3:
197
+            super(Brush, self).__init__(QColor(*components))
198
+        else:
199
+            c = components[0]
200
+            if isinstance(c, QColor):
201
+                super(Brush, self).__init__(c)
202
+            else:
203
+                super(Brush, self).__init__(QColor(c, c, c))
204
+
205
+
206
+class Gradient(QLinearGradient):
207
+    """
208
+    Just a short hand class for the QLinearGradient
209
+    """
210
+    def __init__(self, start=QPoint(0, 0), end=QPoint(0, 0), start_color=Brush(0), end_color=Brush(0)):
211
+        super(Gradient, self).__init__(start.x(), start.y(), end.x(), end.y())
212
+        self.setColorAt(0, start_color)
213
+        self.setColorAt(1, end_color)
214
+
215
+
216
+def line(*widgets):
217
+    """
218
+    Creates a horizontal layout
219
+
220
+    :param widgets: the widgets you wan to add to the layout
221
+
222
+    :return: the horizontal layout
223
+    :rtype: QHBoxLayout
224
+    """
225
+    l = QHBoxLayout()
226
+    apply_layout(l, *widgets)
227
+    return l
228
+
229
+
230
+def col(*widgets):
231
+    """
232
+    Creates a vertical layout
233
+
234
+    :param widgets: the widgets you wan to add to the layout
235
+
236
+    :return: the vertical layout
237
+    :rtype: QVBoxLayout
238
+    """
239
+    l = QVBoxLayout()
240
+    apply_layout(l, *widgets)
241
+    return l
242
+
243
+
244
+def apply_layout(l, *widgets):
245
+    """
246
+    Apply the widgets to the given layout
247
+
248
+    :param       l: the layout
249
+    :type        l: QHBoxLayout | QVBoxLayout
250
+    :param widgets: the widgets you want to add
251
+    """
252
+    skip = isinstance(widgets[0], basestring)
253
+    # if the first element is a string we create a QLabel with this value
254
+    if skip:
255
+        label = QLabel('%s : ' % widgets[0])
256
+        label.setAlignment(Qt.AlignTop)
257
+        label.setFixedWidth(30)
258
+        l.addWidget(label)
259
+        l.setStretch(0, 0)
260
+
261
+    # looping through widget and add them to the given layout
262
+    for i, widget in enumerate(widgets[1 if skip else 0:]):
263
+        try:
264
+            l.addWidget(widget)
265
+        except TypeError:
266
+            l.addLayout(widget)
267
+        l.setStretch(i + 1, int(not isinstance(widget, QLabel)))
0 268
\ No newline at end of file
1 269
new file mode 100644
... ...
@@ -0,0 +1,635 @@
0
+__ordered_dir__ = ['N', 'W', 'S', 'E', 'SW', 'SE', 'NW', 'NE']
1
+
2
+
3
+def Nurbs(injection=None):
4
+    """
5
+    This returns the default settings for Nurbs if injection is empty
6
+
7
+    :param injection: what we want to replace
8
+    :type  injection: str
9
+
10
+    :return: the context menuItems for Nurbs
11
+    :rtype: str
12
+    """
13
+    if not injection:
14
+        return r"""
15
+        populateMMForPaintSkinWeights($item,$radialPositionUsed);
16
+
17
+        string $listRelatives[] = `listRelatives -pa -s $item`;
18
+
19
+        if ( (size($listRelatives) > 0) && ( size ( `findRelatedSkinCluster ( $item )` ) > 0 ) && ( `nodeType $listRelatives[0]` == "nurbsSurface" ) )
20
+        {
21
+
22
+            if(!isRadialPositionUsed($radialPositionUsed,"NW"))
23
+            {
24
+                menuItem -l (uiRes("m_dagMenuProc.kPaintSkinWeightsTool"))
25
+                    -echoCommand true
26
+                    -c ( "ArtPaintSkinWeightsToolOptions; changeSelectMode -object; select -add " + $item)
27
+                    -rp "NW";
28
+                $radialPositionUsed[size($radialPositionUsed)] = "NW";
29
+            }
30
+        }
31
+        for ($i = 0; $i < size($maskList); $i++) {
32
+            $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
33
+            if ($maskList[$i] != "ikfkHandle") {
34
+                if(!isRadialPositionUsed($radialPositionUsed,$radialPosition[$i]))
35
+                {
36
+                    menuItem -label $uiName
37
+                        -ecr false
38
+                        -c ( "doMenuNURBComponentSelection(\"" +
39
+                                $item + "\", \"" +  $maskList[$i] + "\")")
40
+                        -rp $radialPosition[$i];
41
+                }
42
+            }
43
+        }"""
44
+    else:
45
+        return injection
46
+
47
+
48
+def default_Nurbs():
49
+    """
50
+    Yield the defaults values for Nurbs as a 5 length tuples
51
+
52
+    :return: (name, echo command, repeat command, command, position)
53
+    :rtype: tuple
54
+    """
55
+    defaults = [('curveParameterPoint', 'Curve Point'),
56
+                ('controlVertex', 'Control Vertex'),
57
+                ('editPoint', 'Edit Point'),
58
+                ('hull', 'Hull')]
59
+
60
+    for i, default in enumerate(defaults):
61
+        name, nice_name = default
62
+        yield nice_name, False, False, 'doMenuNURBComponentSelection("$item", "%s")' % name, __ordered_dir__[i]
63
+
64
+
65
+def Poly(injection=None):
66
+    """
67
+    This returns the default settings for Polygons if injection is empty
68
+
69
+    :param injection: what we want to replace
70
+    :type  injection: str
71
+
72
+    :return: the context menuItems for Polygons
73
+    :rtype: str
74
+    """
75
+    ret = r"""
76
+        populateMMForPaintSkinWeights($item,$radialPositionUsed);    
77
+
78
+        string $listRelatives[] = `listRelatives -pa -s $item`;
79
+        
80
+        if ( (size($listRelatives) > 0) && ( size ( `findRelatedSkinCluster ( $item )` ) > 0 ) && ( `nodeType $listRelatives[0]` == "mesh" ) )
81
+        {                        
82
+
83
+            if(!isRadialPositionUsed($radialPositionUsed,"NW"))
84
+            {
85
+                menuItem -l (uiRes("m_dagMenuProc.kPolyPaintSkinWeightsTool"))
86
+                    -echoCommand true
87
+                    -c ( "ArtPaintSkinWeightsToolOptions; changeSelectMode -object; select -add " + $item) 
88
+                    -rp "NW";
89
+                $radialPositionUsed[size($radialPositionUsed)] = "NW";
90
+            }
91
+        }"""
92
+
93
+    if not injection:
94
+        ret += r"""
95
+        for ($i = 0; $i < size($maskList); $i++) {
96
+            $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
97
+            if ($maskList[$i] != "ikfkHandle") {
98
+                if(!isRadialPositionUsed($radialPositionUsed,$radialPosition[$i]))
99
+                {
100
+                    menuItem -label $uiName
101
+                        -ecr false
102
+                        -c ( "doMenuComponentSelection(\"" +
103
+                             $item + "\", \"" +  $maskList[$i] + "\")")
104
+                        -rp $radialPosition[$i];
105
+                }
106
+            }
107
+        }"""
108
+    else:
109
+        ret += injection
110
+
111
+    return ret
112
+
113
+
114
+def default_Poly():
115
+    """
116
+    Yield the defaults values for Poly as a 5 length tuples
117
+
118
+    :return: (name, echo command, repeat command, command, position)
119
+    :rtype: tuple
120
+    """
121
+    defaults = [('edge', 'Edge'),
122
+                ('vertex', 'Vertex'),
123
+                ('facet', 'Face'),
124
+                ('puv', 'UV'),
125
+                ('pvf', 'Vertex Face'),
126
+                ('meshComponents', 'Multi')]
127
+    for i, default in enumerate(defaults):
128
+        name, nice_name = default
129
+        yield nice_name, False, False, 'doMenuComponentSelection("$item", "%s")' % name, __ordered_dir__[i]
130
+
131
+
132
+def Joint(injection=None):
133
+    """
134
+    This returns the default settings for Joints if injection is empty
135
+
136
+    :param injection: what we want to replace
137
+    :type  injection: str
138
+
139
+    :return: the context menuItems for Joints
140
+    :rtype: str
141
+    """
142
+    ret = r"""
143
+        string $setCmd = `performSetPrefAngle 2`;
144
+        string $assumeCmd = `performAssumePrefAngle 2`;
145
+        $setCmd += (" "+$item);
146
+        $assumeCmd += (" "+$item);
147
+        string $jts[] = `ls -sl -type joint`;
148
+        for ($jointItem in $jts) {
149
+            if ($jointItem != $item) {
150
+                $setCmd += (" "+$jointItem);
151
+                $assumeCmd += (" "+$jointItem);
152
+            }
153
+        }
154
+
155
+        string  $currContext = `currentCtx`;
156
+        string  $currTool    = `contextInfo -c $currContext`;
157
+        if ( $currTool != "artAttrSkin" )
158
+        {"""
159
+
160
+    if not injection:
161
+        ret += r"""string $hikHandle[] = `listConnections -type hikHandle $item`;
162
+            int $isFBIKjoint = (size($hikHandle) > 0);
163
+            int $isHIKjoint = `objectType -isa hikFKJoint $item`;
164
+            if ($isFBIKjoint || $isHIKjoint) {
165
+                string $reachLocation = "S";
166
+                if ($isHIKjoint) {
167
+                    $reachLocation = "N";
168
+                }
169
+                createFBIKmenuItems($parent, $item, $isFBIKjoint,
170
+                                    $reachLocation,"E","NE","SE");
171
+            } else {
172
+                string $setPreferredQuad = "W";
173
+                string $assumePreferredQuad = "E";
174
+                string $bones[] = `ls -sl -type "joint"`;
175
+                if($item != "")
176
+                {
177
+                    $bones[size($bones)] = $item;
178
+                }
179
+                int $showbs = 0;
180
+                for($bone in $bones)
181
+                {
182
+                    string $connected[] = `listConnections ($bone + ".jointOrient")`;
183
+                    for($symmetryC in $connected)
184
+                    {
185
+                        if(`nodeType $symmetryC` == "symmetryConstraint")
186
+                        {
187
+                            $showbs = 1;
188
+                            break;
189
+                        }
190
+                    }
191
+                }
192
+
193
+                string $breakSymmetryCmd = "string $bones[] = `ls -sl -type \"joint\"`; ";
194
+                if($item != "")
195
+                {
196
+                    $breakSymmetryCmd += "$bones[size($bones)] = \"" + $item + "\";";
197
+                }
198
+                $breakSymmetryCmd += "breakSymmetry($bones);";
199
+                menuItem -label $setPreferred
200
+                    -echoCommand true
201
+                    -c ($setCmd)
202
+                    -rp $setPreferredQuad
203
+                    setPrefAngleItem;
204
+
205
+                menuItem -label $assumePreferred
206
+                    -echoCommand true
207
+                    -c ($assumeCmd)
208
+                    -rp $assumePreferredQuad
209
+                    assumePrefAngleItem;
210
+                if($showbs)
211
+                {
212
+                    menuItem
213
+                        -label (uiRes("m_dagMenuProc.kBreakSymmetry"))
214
+                        -command $breakSymmetryCmd
215
+                        -radialPosition "S";
216
+                }
217
+                menuItem
218
+                    -label (uiRes("m_dagMenuProc.kEditJoints"))
219
+                    -radialPosition "N"
220
+                    -subMenu 1;
221
+
222
+                    menuItem
223
+                        -label (uiRes("m_dagMenuProc.kCreateJoint"))
224
+                        -command "JointTool"
225
+                        -radialPosition "N";
226
+                    menuItem
227
+                        -label (uiRes("m_dagMenuProc.kInsertJoint"))
228
+                        -command "InsertJointTool"
229
+                        -radialPosition "W" ;
230
+                    menuItem
231
+                        -label (uiRes("m_dagMenuProc.kRemoveJoint"))
232
+                        -command "RemoveJoint"
233
+                        -radialPosition "E";
234
+                    setParent -menu ..;
235
+
236
+            }"""
237
+    else:
238
+        ret += injection
239
+
240
+    ret += r"""
241
+        }
242
+        else
243
+        {
244
+            populateMMForPaintSkinWeights($item,$radialPositionUsed);
245
+        }
246
+    """
247
+
248
+    return ret
249
+
250
+
251
+def default_Joint():
252
+    """
253
+    Yield the defaults values for Joints as a 5 length tuples
254
+
255
+    :return: (name, echo command, repeat command, command, position)
256
+    :rtype: tuple
257
+    """
258
+    yield 'Set Preferred Angle', True, True, """string $setCmd = `performSetPrefAngle 2`;
259
+$setCmd += (" " + $item);
260
+string $jts[] = `ls -sl -type joint`;
261
+for ($jointItem in $jts) {
262
+    if ($jointItem != $item) {
263
+        $setCmd += (" "+$jointItem);
264
+    }
265
+}
266
+eval $setCmd;
267
+""", 'W'
268
+
269
+    yield 'Assume Preferred Angle', True, True, """string $assumeCmd = `performAssumePrefAngle 2`;
270
+$assumeCmd += (" " + $item);
271
+string $jts[] = `ls -sl -type joint`;
272
+for ($jointItem in $jts) {
273
+    if ($jointItem != $item) {
274
+        $assumeCmd += (" "+$jointItem);
275
+    }
276
+}
277
+eval $assumeCmd;
278
+""", 'E'
279
+
280
+
281
+def MEL_proc(nurbs=None, poly=None, joint=None):
282
+    """
283
+    This return the whole createSelectMenuItems as a multiline string, inserting given string
284
+    for every variable provided
285
+
286
+    :param  nurbs: insert a nurbs menuItem override
287
+    :param   poly: insert a polygon menuItem override
288
+    :param  joint: insert a joint menuItem override
289
+
290
+    :return: the createSelectMenuItems function
291
+    :rtype: str
292
+    """
293
+    ret = r"""global proc createSelectMenuItems(string $parent, string $item)
294
+{
295
+    string $maskList[] = `objectSelectMasks($item)`;
296
+
297
+    string $radialPosition[];
298
+    string $uiName;
299
+
300
+    int $i;
301
+    int $isNurbObject     = false;
302
+    int $isBezierObject   = false;
303
+    int $isPolyObject     = false;
304
+    int $isLatticeObject  = false;
305
+    int $isJointObject    = false;
306
+    int $isHikEffector      = false;
307
+    int $isIkHandleObject = false;
308
+    int $isIkFkHandleObject = false;
309
+    int $isParticleObject = false;
310
+    int $isSpringObject   = false;
311
+    int $isSubdivObject   = false;
312
+    int $isLocatorObject  = false;
313
+    int $hasComponents      = false;
314
+    int $isMotionTrail    = false;
315
+
316
+    if (1 <= size($maskList)) {
317
+        $isLatticeObject = ($maskList[0] == "latticePoint");
318
+        $isJointObject = ($maskList[0] == "joint");
319
+        $isHikEffector = ($maskList[0] == "hikEffector");
320
+        $isIkHandleObject = ($maskList[0] == "ikHandle");
321
+        $isParticleObject = ($maskList[0] == "particle");
322
+        $isSpringObject = ($maskList[0] == "springComponent");
323
+        $isSubdivObject = ($maskList[0] == "subdivMeshPoint");
324
+        $isLocatorObject = ($maskList[0] == "locator");
325
+        $isMotionTrail = ($maskList[0] == "motionTrail");
326
+    }
327
+    if (2 <= size($maskList)) {
328
+        $isBezierObject = ($maskList[1] == "bezierAnchor");
329
+        $isNurbObject = ($maskList[1] == "controlVertex");
330
+        $isPolyObject = ($maskList[1] == "vertex");
331
+    }
332
+
333
+    int $maskSize = size($maskList);
334
+    int $maxRadialPos = size($maskList);
335
+
336
+    if (($maskSize > 0) && ($maskList[$maskSize-1] == "ikfkHandle")) {
337
+        $isIkFkHandleObject = true;
338
+        $maxRadialPos--;
339
+    }
340
+
341
+    $hasComponents = $isLatticeObject ||
342
+                     $isParticleObject ||
343
+                     $isSubdivObject ||
344
+                     $isSpringObject ||
345
+                     $isNurbObject ||
346
+                     $isPolyObject ||
347
+                     $isBezierObject;
348
+
349
+    setParent -menu $parent;
350
+    $radialPosition[0] = "N";
351
+    $radialPosition[1] = "W";
352
+    $radialPosition[2] = "S";
353
+    $radialPosition[3] = "E";
354
+    $radialPosition[4] = "SW";
355
+    $radialPosition[5] = "SE";
356
+    $radialPosition[6] = "NW";
357
+    $radialPosition[7] = "NE";
358
+
359
+    string $radialPositionUsed[];
360
+
361
+    string $disableikHandle = (uiRes("m_dagMenuProc.kDisableIkHandle"));
362
+    string $enableIkHandle  = (uiRes("m_dagMenuProc.kEnableIkHandle"));
363
+    string $setPreferred    = (uiRes("m_dagMenuProc.kSetPreferredAngle"));
364
+    string $assumePreferred = (uiRes("m_dagMenuProc.kAssumePreferredAngle"));
365
+
366
+    if( $isBezierObject ) {
367
+        for ($i = 0; $i < size($maskList); $i++) {
368
+              $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
369
+            if ($maskList[$i] != "ikfkHandle") {
370
+                string $mask = $maskList[$i];
371
+                if( $mask == "bezierAnchor" )
372
+                {
373
+                    $mask = "controlVertex";
374
+                }
375
+                if( $mask == "editPoint" )
376
+                {
377
+                    continue;
378
+                }
379
+                menuItem -label $uiName
380
+                    -ecr false
381
+                    -c ( "doMenuNURBComponentSelection(\"" +
382
+                         $item + "\", \"" +  $mask + "\")")
383
+                    -rp $radialPosition[$i];
384
+            }
385
+        }
386
+    }
387
+    else if ($isNurbObject) {"""
388
+
389
+    ret += Nurbs(nurbs)
390
+
391
+    ret += r"""} else if ($isPolyObject) {"""
392
+
393
+    ret += Poly(poly)
394
+
395
+    ret += r"""} else if ($isLatticeObject) {
396
+        for ($i = 0; $i < size($maskList); $i++) {
397
+            if ($maskList[$i] != "ikfkHandle") {
398
+                $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
399
+                menuItem -label $uiName
400
+                    -ecr false
401
+                    -c ( "doMenuLatticeComponentSelection(\"" +
402
+                         $item + "\", \"" +  $maskList[$i] + "\")")
403
+                    -rp $radialPosition[$i];
404
+            }
405
+        }
406
+    } else if ($isJointObject) {"""
407
+
408
+    ret += Joint(joint)
409
+
410
+    ret += r"""} else if ($isHikEffector){
411
+        if (nodeType($item) == "hikFloorContactMarker") {
412
+            string $parentItems[] = `listRelatives -pa -p $item`;
413
+            if (size($parentItems) &&
414
+                (nodeType($parentItems[0]) == "hikEffector") || nodeType($parentItems[0]) == "hikIKEffector") {
415
+                $item = $parentItems[0];
416
+            } else {
417
+                $isHikEffector = false;
418
+            }
419
+        }
420
+
421
+        if ($isHikEffector) {
422
+            string $pivotOffsetPlug = $item + ".pivotOffset";
423
+            float $pivotOffset[] = `getAttr $pivotOffsetPlug`;
424
+            int $enablePin = (equivalentTol($pivotOffset[0],0.0,0.001) &&
425
+                              equivalentTol($pivotOffset[1],0.0,0.001) &&
426
+                              equivalentTol($pivotOffset[2],0.0,0.001));
427
+
428
+            menuItem -label (uiRes("m_dagMenuProc.kPinBoth"))
429
+                -echoCommand true
430
+                -c ("doPinHikEffectors 1 {\"3\",\"" + $item + "\", \"1\" };")
431
+                -enable $enablePin
432
+                -rp "SW"
433
+                pinAllItem;
434
+
435
+            if (! `exists checkMultiSelectPinState`) {
436
+                eval ("source \"doPinHikEffectors.mel\"");
437
+            }
438
+
439
+            int $currentPinT = checkMultiSelectPinState($item,1);
440
+            string $pinTlabel = (uiRes("m_dagMenuProc.kPinTranslate"));
441
+            if ($currentPinT == 1) {
442
+                $pinTlabel = (uiRes("m_dagMenuProc.kPinTranslateStar"));
443
+            }
444
+            int $currentPinR = checkMultiSelectPinState($item,0);
445
+            string $pinRlabel = (uiRes("m_dagMenuProc.kPinRotate"));
446
+            if ($currentPinR == 1) {
447
+                $pinRlabel = (uiRes("m_dagMenuProc.kPinRotateStar"));
448
+            }
449
+
450
+            menuItem -label $pinTlabel
451
+                -echoCommand true
452
+                -c ("doPinHikEffectors 1 {\"1\",\"" + $item + "\", \"1\", \"1\" };")
453
+                -enable $enablePin
454
+                -rp "NW"
455
+                pinTransItem;
456
+
457
+            menuItem -label $pinRlabel
458
+                -echoCommand true
459
+                -c ("doPinHikEffectors 1 {\"2\",\"" + $item + "\", \"1\", \"1\" };")
460
+                -enable $enablePin
461
+                -rp "W"
462
+                pinRotItem;
463
+
464
+            menuItem -label (uiRes("m_dagMenuProc.kUnpinBoth"))
465
+                -echoCommand true
466
+                -c ("doPinHikEffectors 1 {\"0\",\"" + $item + "\", \"1\" };")
467
+                -rp "S"
468
+                unpinItem;
469
+
470
+            int $includeReachMode = (nodeType($item) == "hikEffector");
471
+            createFBIKmenuItems($parent, $item,
472
+                                $includeReachMode,"N",
473
+                                "E","NE","SE");
474
+        }
475
+    } else if ($isLocatorObject) {
476
+        populateMMForPaintSkinWeights($item,$radialPositionUsed);
477
+
478
+    } else if ($isIkHandleObject) {
479
+        string $selectikHandlesJointsAnnot = (uiRes("m_dagMenuProc.kSelectikHandlesAnnot"));
480
+        string $selectikHandlesAnnot = (uiRes("m_dagMenuProc.kEnableIKHandlesAnnot"));
481
+        menuItem -label $setPreferred
482
+            -annotation $selectikHandlesJointsAnnot
483
+            -echoCommand true
484
+            -c (`performSetPrefAngle 2` + " " + $item)
485
+            -rp "W"
486
+            setPrefAngleItem;
487
+
488
+        menuItem -label $assumePreferred
489
+            -annotation $selectikHandlesJointsAnnot
490
+            -echoCommand true
491
+            -c (`performAssumePrefAngle 2` + " " + $item)
492
+            -rp "E"
493
+            assumePrefAngleItem;
494
+
495
+        menuItem -label $enableIkHandle
496
+            -annotation $selectikHandlesAnnot
497
+            -echoCommand true
498
+            -c ("ikHandle -e -eh " + $item)
499
+            -rp "N"
500
+            enableIKHandlesItem;
501
+
502
+        menuItem -label $disableikHandle
503
+            -annotation $selectikHandlesAnnot
504
+            -echoCommand true
505
+            -c ("ikHandle -e -dh " + $item)
506
+            -rp "S"
507
+            disableIKHandlesItem;
508
+
509
+        menuItem -label (uiRes("m_dagMenuProc.kEnableSnap"))
510
+            -annotation $selectikHandlesAnnot
511
+            -echoCommand true
512
+            -c ("ikHandle -e -see " + $item + ";" +
513
+                "ikHandle -e -shf on " + $item)
514
+            -rp "SE"
515
+            enableIKHandlesSnapItem;
516
+
517
+        menuItem -label (uiRes("m_dagMenuProc.kDisableSnap"))
518
+            -annotation $selectikHandlesAnnot
519
+            -echoCommand true
520
+            -c ("ikHandle -e -shf off " + $item)
521
+            -rp "SW"
522
+            disableIKHandlesSnapItem;
523
+
524
+        $maxRadialPos = 6;
525
+    } else if ($isParticleObject) {
526
+        for ($i = 0; $i < size($maskList); $i++) {
527
+               $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
528
+            menuItem -label $uiName
529
+                -ecr false
530
+                -c ( "doMenuParticleComponentSelection(\"" +
531
+                    $item + "\", \"" +  $maskList[$i] + "\")")
532
+                -rp $radialPosition[$i];
533
+        }
534
+    } else if ($isSpringObject) {
535
+        for ($i = 0; $i < size($maskList); $i++) {
536
+               $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
537
+            menuItem -label $uiName
538
+                -ecr false
539
+                -c ( "doMenuSpringComponentSelection(\"" +
540
+                    $item + "\", \"" +  $maskList[$i] + "\")")
541
+                -rp $radialPosition[$i];
542
+        }
543
+    } else if ($isSubdivObject) {
544
+        subdDagMenuProc( 0, $item, $maskList );
545
+    } else if ($isMotionTrail) {
546
+        motionTrailDagMenuProc( $item );
547
+    } else {
548
+        for ($i = 0; $i < size($maskList); $i++) {
549
+            if ($maskList[$i] == "ikfkHandle") {
550
+                continue;
551
+            }
552
+
553
+            $uiName = `dagMenuProc_selectionMask_melToUI $maskList[$i]`;
554
+            menuItem -label $uiName
555
+                -ecr false
556
+                -c ( "doMenuComponentSelection(\"" +
557
+                    $item + "\", \"" +  $maskList[$i] + "\")")
558
+                -rp $radialPosition[$i];
559
+        }
560
+    }
561
+
562
+    if ($hasComponents) {
563
+        menuItem -label (uiRes("m_dagMenuProc.kObjectMode"))
564
+                -ecr false
565
+                -c ("maintainActiveChangeSelectMode " + $item + ";")
566
+                -rp "NE";
567
+    }
568
+
569
+    if ($isIkFkHandleObject) {
570
+        string $handle = getControlledHandle($item);
571
+
572
+        if ($maxRadialPos < 8) {
573
+            menuItem -label (uiRes("m_dagMenuProc.kSetIKFKKey"))
574
+                -echoCommand true
575
+                -annotation (uiRes("m_dagMenuProc.kSetKeysAnnot"))
576
+                -rp $radialPosition[7]
577
+                -command ("select -r "+$item+"; SetIKFKKeyframe");
578
+        }
579
+
580
+        if ($maxRadialPos < 7) {
581
+            menuItem -label (uiRes("m_dagMenuProc.kMoveIKToFK"))
582
+                -echoCommand true
583
+                -annotation (uiRes("m_dagMenuProc.kSelectAnIKHandleOrIKFKAnnot"))
584
+                -rp $radialPosition[6]
585
+                -command ("select -r "+$item+"; MoveIKtoFK");
586
+        }
587
+
588
+        if ($maxRadialPos < 5) {
589
+            menuItem -label $disableikHandle
590
+                -annotation (uiRes("m_dagMenuProc.kDisableIKHandleAnnot"))
591
+                -echoCommand true
592
+                -c ("ikHandle -e -dh " + $handle)
593
+                -rp $radialPosition[5];
594
+
595
+            menuItem -label $enableIkHandle
596
+                -annotation (uiRes("m_dagMenuProc.kEnableIKHandleAnnot"))
597
+                -echoCommand true
598
+                -c ("ikHandle -e -eh " + $handle)
599
+                -rp $radialPosition[4];
600
+        }
601
+    }
602
+
603
+    setParent -menu $parent;
604
+}"""
605
+    return ret
606
+
607
+
608
+def MEL_multiline(script='', var_name='multiLine_Script'):
609
+    """
610
+    This create a multiline string in mel and reformat the \\ in order to exit
611
+    the double quotes
612
+
613
+    :param   script: the script we want to reformat
614
+    :type    script: str
615
+    :param var_name: the wanted variable name
616
+    :type  var_name: str
617
+
618
+    :return: reformatted script
619
+    :rtype: str
620
+    """
621
+    ret = 'string $%s = ' % var_name
622
+
623
+    # we split each line and reformat it properly
624
+    for i, line in enumerate(script.split('\n')):
625
+        if i:
626
+            ret += '+ '
627
+        ret += '"%s\\n"\n' % line.replace('"', '\\"')
628
+
629
+    # final
630
+    ret += ';'
631
+
632
+    # we finally exit the \\" to \\\" so it can be inserted in another string
633
+    return ret.replace(r'\\"', r'\\\"')
634
+
0 635
new file mode 100644
... ...
@@ -0,0 +1,601 @@
0
+"""
1
+All visual tools & widgets
2
+"""
3
+from math import cos, sin, pi
4
+from copy import copy
5
+
6
+try:
7
+    from PySide.QtCore import QPoint, Signal, QRect, Qt, QMimeData, QPointF, QRectF
8
+    from PySide.QtGui import QWidget, QColor, QFont, QFontMetrics, QApplication, QDrag, QPixmap, QPainter, QIcon, \
9
+        QLinearGradient, QPolygonF, QGroupBox, QLineEdit, QLabel
10
+except ImportError:
11
+    from PySide2.QtCore import QPoint, Signal, QRect, Qt, QMimeData, QPointF, QRectF
12
+    from PySide2.QtWidgets import QWidget, QApplication, QLineEdit, QGroupBox, QLabel
13
+    from PySide2.QtGui import QColor, QFont, QFontMetrics, QDrag, QPixmap, QPainter, QIcon, QLinearGradient, QPolygonF
14
+
15
+from .misc import Pen, Brush, __dirs__, __pos__, Gradient
16
+from .proc import default_Nurbs, default_Poly, default_Joint
17
+
18
+
19
+class Radial_Button(QWidget):
20
+    """
21
+    This is the hotBox buttons visual widget, can be drag & drop and accepts drops
22
+    """
23
+    # signals
24
+    selected = Signal(str)
25
+
26
+    # visual
27
+    background = Brush(70)
28
+    border = Pen(63, 2)
29
+    color = Pen(200)
30
+
31
+    background_selected = Gradient(QPoint(0, 4), QPoint(0, 20), QColor(75, 149, 255), QColor(66, 128, 255))
32
+    border_selected = Pen(255)
33
+
34
+    background_over = Gradient(QPoint(0, 4), QPoint(0, 20), QColor(106, 146, 184), QColor(92, 126, 159))
35
+    color_over = Pen(255)
36
+
37
+    def __init__(self, parent=None, position='N', name=None):
38
+        super(Radial_Button, self).__init__(parent)
39
+        # settings
40
+        self.empty = not bool(name)
41
+        self.over = False
42
+        self.isSelected = False
43
+        self.setMouseTracking(True)
44
+        self.setAcceptDrops(True)
45
+
46
+        # visual
47
+        self.popup_font = QFont('Tahoma', 10)
48
+        self.popup_metrics = QFontMetrics(self.popup_font)
49
+
50
+        self._pos = position
51
+        self.bbox = QRect(2, 2, self.width() - 4, self.height() - 4)
52
+
53
+        self.setMinimumWidth(100)
54
+        self.setFixedHeight(22)
55
+        self.setFixedWidth(120)
56
+
57
+        # content
58
+        self.position = position
59
+        self.abstract = None
60
+        self._name = position if not name else name
61
+
62
+    # SETTERS
63
+    @property
64
+    def position(self):
65
+        return self._pos
66
+
67
+    @position.setter
68
+    def position(self, position):
69
+        self._pos = position
70
+        self.setBBox()
71
+
72
+    @property
73
+    def name(self):
74
+        return self._name
75
+
76
+    @name.setter
77
+    def name(self, name):
78
+        self.empty = name in __dirs__ and name == self.position
79
+        # 2DO: check valid name
80
+        self._name = name
81
+
82
+    # BUILT IN
83
+    def dragEnterEvent(self, e):
84
+        # if we are dragging a correct item over this one
85
+        if e.mimeData().hasText() and e.source() != self:
86
+            e.acceptProposedAction()
87
+            self.over = True
88
+            self.repaint()
89
+
90
+        else:
91
+            e.ignore()
92
+
93
+    def dragLeaveEvent(self, e):
94
+        self.over = False
95
+        self.repaint()
96
+
97
+    def dropEvent(self, e):
98
+        def paste(from_hb, to_hb):
99
+            """
100
+            Small function to paste data from an Abstract HotBox to another
101
+
102
+            :param from_hb: source
103
+            :type  from_hb: Abstract_Menu
104
+            :param   to_hb: destination
105
+            :type    to_hb: Abstract_Menu
106
+            """
107
+            to_hb.abstract.title = from_hb.abstract.title
108
+            to_hb.abstract.code = from_hb.abstract.code
109
+            to_hb.abstract.type = from_hb.abstract.type
110
+            to_hb.abstract.style = from_hb.abstract.style
111
+            to_hb.abstract.param = from_hb.abstract.param
112
+
113
+        mime = e.mimeData()
114
+        pos = mime.text()
115
+        # if the position seems correct we drop the button over the new one
116
+        if pos in __dirs__:
117
+            button = self.parent()[pos]
118
+
119
+            # if we are moving the button
120
+            if e.dropAction() == Qt.MoveAction:
121
+                # on an empty one we just drop and empty the previous pos
122
+                if self.empty:
123
+                    paste(button, self)
124
+                    button.setEmpty()
125
+
126
+                # otherwise we swap the two buttons
127
+                else:
128
+                    title = copy(button.abstract.title)
129
+                    code = copy(button.abstract.code)
130
+                    type = copy(button.abstract.type)
131
+                    style = copy(button.abstract.style)
132
+                    param = copy(button.abstract.param)
133
+
134
+                    button.abstract.title = copy(self.abstract.title)
135
+                    button.abstract.code = copy(self.abstract.code)
136
+                    button.abstract.type = copy(self.abstract.type)
137
+                    button.abstract.style = copy(self.abstract.style)
138
+                    button.abstract.param = copy(self.abstract.param)
139
+
140
+                    self.abstract.title = title
141
+                    self.abstract.code = code
142
+                    self.abstract.type = type
143
+                    self.abstract.style = style
144
+                    self.abstract.param = param