multi-user/utils.py
2019-09-20 22:37:32 +02:00

231 lines
6.5 KiB
Python

import logging
import sys
from uuid import uuid4
import json
import os
import string
import random
import bpy
import mathutils
from . import presence, environment
from .libs import dump_anything
# TODO: replace hardcoded values...
BPY_TYPES = {'Image': 'images', 'Texture': 'textures', 'Material': 'materials', 'GreasePencil': 'grease_pencils', 'Curve': 'curves', 'Collection': 'collections', 'Mesh': 'meshes', 'Object': 'objects',
'Scene': 'scenes', 'Light': 'lights', 'SunLight': 'lights', 'SpotLight': 'lights', 'AreaLight': 'lights', 'PointLight': 'lights', 'Camera': 'cameras', 'Action': 'actions', 'Armature': 'armatures'}
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def get_users(datablock):
users = []
supported_types = bpy.context.window_manager.session.supported_datablock
if hasattr(datablock, 'users_collection') and datablock.users_collection:
users.extend(list(datablock.users_collection))
if hasattr(datablock, 'users_scene') and datablock.users_scene:
users.extend(list(datablock.users_scene))
if hasattr(datablock, 'users_group') and datablock.users_scene:
users.extend(list(datablock.users_scene))
for datatype in supported_types:
if datatype.bl_name != 'users':
root = getattr(bpy.data,datatype.bl_name)
for item in root:
if hasattr(item, 'data') and datablock == item.data or \
datatype.bl_name != 'collections' and hasattr(item, 'children') and datablock in item.children:
users.append(item)
return users
# UTILITY FUNCTIONS
def random_string_digits(stringLength=6):
"""Generate a random string of letters and digits """
lettersAndDigits = string.ascii_letters + string.digits
return ''.join(random.choice(lettersAndDigits) for i in range(stringLength))
def clean_scene():
for datablock in BPY_TYPES:
datablock_ref = getattr(bpy.data, BPY_TYPES[datablock])
for item in datablock_ref:
try:
datablock_ref.remove(item)
# Catch last scene remove
except RuntimeError:
pass
def revers(d):
l = []
for i in d:
l.append(i)
return l[::-1]
def get_armature_edition_context(armature):
override = {}
# Set correct area
for area in bpy.data.window_managers[0].windows[0].screen.areas:
if area.type == 'VIEW_3D':
override = bpy.context.copy()
override['area'] = area
break
# Set correct armature settings
override['window'] = bpy.data.window_managers[0].windows[0]
override['screen'] = bpy.data.window_managers[0].windows[0].screen
override['mode'] = 'EDIT_ARMATURE'
override['active_object'] = armature
override['selected_objects'] = [armature]
for o in bpy.data.objects:
if o.data == armature:
override['edit_object'] = o
break
return override
def get_selected_objects(scene):
return [obj.name for obj in scene.objects if obj.select_get()]
def load_dict(src_dict, target):
try:
for item in src_dict:
# attr =
setattr(target, item, src_dict[item])
except Exception as e:
logger.error(e)
pass
def resolve_bpy_path(path):
"""
Get bpy property value from path
"""
item = None
try:
path = path.split('/')
item = getattr(bpy.data, BPY_TYPES[path[0]])[path[1]]
except:
pass
return item
def load_client(client=None, data=None):
C = bpy.context
D = bpy.data
net_settings = C.window_manager.session
if client and data:
if net_settings.enable_presence:
draw.renderer.draw_client(data)
draw.renderer.draw_client_selected_objects(data)
def load_armature(target=None, data=None, create=False):
file = "cache_{}.json".format(data['name'])
context = bpy.context
if not target:
target = bpy.data.armatures.new(data['name'])
dump_anything.load(target, data)
with open(file, 'w') as fp:
json.dump(data, fp)
fp.close()
target.id = data['id']
else:
# Construct a correct execution context
file = "cache_{}.json".format(target.name)
with open(file, 'r') as fp:
data = json.load(fp)
if data:
ob = None
for o in bpy.data.objects:
if o.data == target:
ob = o
if ob:
bpy.context.view_layer.objects.active = ob
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
for eb in data['edit_bones']:
if eb in target.edit_bones.keys():
# Update the bone
pass
else:
# Add new edit bone and load it
target_new_b = target.edit_bones.new[eb]
dump_anything.load(target_new_b, data['bones'][eb])
logger.debug(eb)
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
fp.close()
import os
os.remove(file)
def dump_datablock(datablock, depth):
if datablock:
dumper = dump_anything.Dumper()
dumper.type_subset = dumper.match_subset_all
dumper.depth = depth
datablock_type = datablock.bl_rna.name
key = "{}/{}".format(datablock_type, datablock.name)
data = dumper.dump(datablock)
return data
def dump_datablock_attibutes(datablock=None, attributes=[], depth=1, dickt=None):
if datablock:
dumper = dump_anything.Dumper()
dumper.type_subset = dumper.match_subset_all
dumper.depth = depth
datablock_type = datablock.bl_rna.name
data = {}
if dickt:
data = dickt
for attr in attributes:
try:
data[attr] = dumper.dump(getattr(datablock, attr))
except:
pass
return data
def init_client(key=None):
client_dict = {}
C = bpy.context
Net = C.window_manager.session
client_dict['uuid'] = str(uuid4())
client_dict['location'] = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
client_dict['color'] = [Net.client_color.r,
Net.client_color.g, Net.client_color.b, 1]
client_dict['active_objects'] = get_selected_objects(C.view_layer)
return client_dict