Update
This commit is contained in:
102
2023/scripts/animation_tools/dwpicker/scenedata.py
Normal file
102
2023/scripts/animation_tools/dwpicker/scenedata.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
from maya import cmds
|
||||
|
||||
from .compatibility import ensure_retro_compatibility
|
||||
from .namespace import maya_namespace, node_full_namespace
|
||||
from .optionvar import USE_BASE64_DATA_ENCODING
|
||||
|
||||
|
||||
PICKER_HOLDER_NODE = '_dwpicker_data'
|
||||
PICKER_HOLDER_ATTRIBUTE = '_dwpicker_data'
|
||||
LS_EXP = ["*." + PICKER_HOLDER_ATTRIBUTE, "*:*." + PICKER_HOLDER_ATTRIBUTE]
|
||||
|
||||
|
||||
def get_picker_holder_node():
|
||||
if cmds.objExists(PICKER_HOLDER_NODE):
|
||||
return PICKER_HOLDER_NODE
|
||||
return create_picker_holder_node()
|
||||
|
||||
|
||||
def create_picker_holder_node():
|
||||
with maya_namespace(":"):
|
||||
selection = cmds.ls(selection=True)
|
||||
node = cmds.createNode('script', name=PICKER_HOLDER_NODE)
|
||||
cmds.select(selection)
|
||||
cmds.setAttr(node + '.nodeState', 1)
|
||||
cmds.addAttr(node, longName=PICKER_HOLDER_ATTRIBUTE, dataType='string')
|
||||
return node
|
||||
|
||||
|
||||
def store_local_picker_data(pickers):
|
||||
data = encode_data(pickers)
|
||||
node = get_picker_holder_node()
|
||||
cmds.setAttr(node + '.' + PICKER_HOLDER_ATTRIBUTE, data, type='string')
|
||||
clean_stray_picker_holder_nodes()
|
||||
|
||||
|
||||
def load_local_picker_data():
|
||||
nodes = list_picker_holder_nodes()
|
||||
pickers = []
|
||||
for node in nodes:
|
||||
data = cmds.getAttr(node + '.' + PICKER_HOLDER_ATTRIBUTE)
|
||||
if not data:
|
||||
continue
|
||||
data = [ensure_retro_compatibility(p) for p in decode_data(data)]
|
||||
namespace = node_full_namespace(node)
|
||||
if namespace:
|
||||
# holder node would have namespace when it is referenced
|
||||
# and we should add it's namespace for items to be selectable
|
||||
for p in data:
|
||||
for s in p['shapes']:
|
||||
s['action.targets'] = [
|
||||
re.sub(r'([^|]+)', r'{}:\1'.format(namespace), n)
|
||||
for n in s['action.targets']]
|
||||
pickers.extend(data)
|
||||
return pickers
|
||||
|
||||
|
||||
def encode_data(pickers):
|
||||
data = json.dumps(pickers)
|
||||
if not cmds.optionVar(query=USE_BASE64_DATA_ENCODING):
|
||||
return data
|
||||
# Ensure backward compatibility.
|
||||
if sys.version_info[0] == 2:
|
||||
return base64.b64encode(bytes(data))
|
||||
return base64.b64encode(bytes(data, "utf-8"))
|
||||
|
||||
|
||||
def decode_data(data):
|
||||
try:
|
||||
return json.loads(data)
|
||||
except ValueError: # Happe if data encoded is encoded as base 64 string.
|
||||
return json.loads(base64.b64decode(data))
|
||||
|
||||
|
||||
def list_picker_holder_nodes():
|
||||
"""
|
||||
Look up in the scene all the nodes holding an attribute named
|
||||
"_dwpicker_holder" which are not set on the "_dwpicker_holder" node.
|
||||
This mignt happed if a node node is imported (creating a namespace or a
|
||||
incrementation).
|
||||
"""
|
||||
return [node.split(".")[0] for node in cmds.ls(LS_EXP)]
|
||||
|
||||
|
||||
def clean_stray_picker_holder_nodes():
|
||||
"""
|
||||
If the scene contains multiple picker holder nodes, we remove them
|
||||
automatically to avoid repeated pickers.
|
||||
"""
|
||||
for node in list_picker_holder_nodes():
|
||||
if node == PICKER_HOLDER_NODE:
|
||||
continue
|
||||
cmds.delete(node)
|
||||
if cmds.objExists(node):
|
||||
# Node is locked or in reference and cannot be removed.
|
||||
# As we cant remove it, we reset his data to avoid double pickers.
|
||||
cmds.setAttr(
|
||||
node + "." + PICKER_HOLDER_ATTRIBUTE, "", type="string")
|
||||
Reference in New Issue
Block a user