231 lines
6.5 KiB
Python
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
|