i wanted a bit more control over ui button placement and handles, scaleing is broken in 2020 so was having to do a lot with handles and it was awkward getting things to line up.
i wanted some snapping and the ability to undo. so i started thinking nurbs curves?
so i wrote a couple of functions for getting button as curves, figured it might be useful for others too.
the first function gets the data dictionary from the ui and using the data build a nurbs curve for each button, these curves can then be edited as normal, shapes nodes can be swapped and the the second function over writes the picker data node in the scene, cvs are baked relative to pivots so scale and rotate data on the transform is applied.
i am pretty new to this code so i think i captured all the data and re-apply it on the other end but i may have missed some stuff.
this has only been tested a little on maya 2020.2
import pymel.core as pm
from PySide2 import QtGui
import mgear.core.attribute as attr
import mgear.anim_picker
from mgear.core import pyqt
import json
def extract_picker_data(factor = 0.1, background_fade = 0.5, showCVs=True):
animPickerUI = pyqt.get_instance(pyqt.get_main_window(), mgear.anim_picker.gui.MainDockWindow)
data = animPickerUI.get_character_data()
grp = pm.group(em=True, n='pickerData_extraction')
for tab in data['tabs']:
picker_grp = pm.group(em=True, n=tab['name'], p=grp)
if 'background' in tab['data'].keys():
ip = pm.imagePlane(n='{}_background'.format(tab['name']))
ip[0].tz.set(-1)
ip[0].overrideEnabled.set(1)
ip[0].overrideDisplayType.set(2)
ip[1].alphaGain.set(background_fade)
pm.parent(ip[0], picker_grp)
q_image = QtGui.QImage(tab['data']['background'])
ip[1].imageName.set(tab['data']['background'])
ip[1].width.set(q_image.size().width() * factor)
ip[1].height.set(q_image.size().height() * factor)
for item in tab['data']['items']:
handles = item['handles']
pos_x, pos_y = item['position']
item_curve = pm.circle(d=1, s=len(item['handles']), ch=False)[0]
pm.parent(item_curve, picker_grp)
pm.closeCurve(item_curve, ch=False, ps=2, rpo=True)
item_curve.displayHandle.set(1)
if showCVs:
item_curve.getShape().dispCV.set(1)
q_color = QtGui.QColor(*item['color'])
attr.addColorAttribute(item_curve, 'color', q_color.getRgbF()[:3])
attr.addAttribute(item_curve, 'alpha', 'long', item['color'][3], minValue=0, maxValue=255)
item_curve.overrideEnabled.set(1)
item_curve.overrideRGBColors.set(1)
item_curve.color >> item_curve.overrideColorRGB
item_curve.rotatePivot >> item_curve.selectHandle
if 'controls' in item.keys():
attr.addAttribute(item_curve, 'controls', 'string', json.dumps(item['controls']))
if 'action_mode' in item.keys():
attr.addAttribute(item_curve, 'action_mode', 'bool', item['action_mode'])
attr.addAttribute(item_curve, 'action_script', 'string', item['action_script'])
if 'menus' in item.keys():
attr.addAttribute(item_curve, 'menus', 'string', json.dumps(item['menus']))
if 'text' in item.keys():
attr.addAttribute(item_curve, 'text_data', 'string', json.dumps({'text': item['text'],
'text_color': item['text_color'],
'text_size': item['text_size']}))
for i, (x, y) in enumerate(handles):
item_curve.getShape().controlPoints[i].set(x * factor, y * factor, 0)
item_curve.t.set(pos_x * factor, pos_y * factor, 0)
def overwrite_picker_data(factor = 0.1, data_node='PICKER_DATA', deleteCurves=True):
grp = pm.PyNode('pickerData_extraction')
new_data = {'tabs': []}
upscale = lambda x, y: [x * (1 / factor), y * (1 / factor)]
for tab_grp in grp.listRelatives():
new_data['tabs'].append({'name': tab_grp.name()})
new_data['tabs'][-1]['data'] = {'items': []}
bg_imagePlane = tab_grp.listRelatives(type='imagePlane', ad=True)
if bg_imagePlane:
new_data['tabs'][-1]['data']['background'] = bg_imagePlane[0].imageName.get()
for item_curve in [ic for ic in tab_grp.listRelatives() if ic.getShape().type() != 'imagePlane']:
item_data = {}
if item_curve.hasAttr('action_mode'):
item_data['action_mode'] = True
item_data['action_script'] = item_curve.action_script.get()
# color
q_color = QtGui.QColor()
q_color.setRgbF(*item_curve.color.get())
q_color.setAlpha(item_curve.alpha.get())
item_data['color'] = q_color.getRgb()
# controls
if item_curve.hasAttr('controls'):
item_data['controls'] = json.loads(item_curve.controls.get())
# position
item_data['position'] = upscale(*list(item_curve.getPivots(ws=True))[0][:2])
# handles
item_curve.f.get()
handles = []
for cv in item_curve.cv[:-1 if item_curve.f.get() == 0 else None]:
x, y = upscale(*cv.getPosition(space='world')[:2])
handles.append([x - item_data['position'][0], y - item_data['position'][1]])
item_data['handles'] = handles
# menus
if item_curve.hasAttr('menus'):
item_data['menus'] = json.loads(item_curve.menus.get())
# text
if item_curve.hasAttr('text_data'):
item_data.update(json.loads(item_curve.text_data.get()))
new_data['tabs'][-1]['data']['items'].append(item_data)
if deleteCurves:
pm.delete(grp)
data_node = pm.PyNode(data_node)
data_node.picker_datas.set(l=False)
data_node.picker_datas.set(json.dumps(new_data).replace('true', 'True'))
data_node.picker_datas.set(l=True)
animPickerUI = pyqt.get_instance(pyqt.get_main_window(), mgear.anim_picker.gui.MainDockWindow)
animPickerUI.refresh()