# ##### BEGIN GPL LICENSE BLOCK ##### # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # ##### END GPL LICENSE BLOCK ##### import json import logging import os import sys import time from collections.abc import Iterable from pathlib import Path from uuid import uuid4 import math import bpy import mathutils from . import environment, presence def find_from_attr(attr_name, attr_value, list): for item in list: if getattr(item, attr_name, None) == attr_value: return item return None def get_datablock_users(datablock): users = [] supported_types = get_preferences().supported_datablocks 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 def clean_scene(): for type_name in dir(bpy.data): try: type_collection = getattr(bpy.data, type_name) for item in type_collection: type_collection.remove(item) except: continue def get_selected_objects(scene, active_view_layer): return [obj.uuid for obj in scene.objects if obj.select_get(view_layer=active_view_layer)] def resolve_from_id(id, optionnal_type=None): for category in dir(bpy.data): root = getattr(bpy.data, category) if isinstance(root, Iterable): if id in root and ((optionnal_type is None) or (optionnal_type.lower() in root[id].__class__.__name__.lower())): return root[id] return None def get_datablock_from_uuid(uuid, default, ignore=[]): if not uuid: return default for category in dir(bpy.data): root = getattr(bpy.data, category) if isinstance(root, Iterable) and category not in ignore: for item in root: if getattr(item, 'uuid', None) == uuid: return item return default def get_preferences(): return bpy.context.preferences.addons[__package__].preferences def current_milli_time(): return int(round(time.time() * 1000)) def get_expanded_icon(prop: bpy.types.BoolProperty) -> str: if prop: return 'DISCLOSURE_TRI_DOWN' else: return 'DISCLOSURE_TRI_RIGHT' # Taken from here: https://stackoverflow.com/a/55659577 def get_folder_size(folder): return ByteSize(sum(file.stat().st_size for file in Path(folder).rglob('*'))) class ByteSize(int): _kB = 1024 _suffixes = 'B', 'kB', 'MB', 'GB', 'PB' def __new__(cls, *args, **kwargs): return super().__new__(cls, *args, **kwargs) def __init__(self, *args, **kwargs): self.bytes = self.B = int(self) self.kilobytes = self.kB = self / self._kB**1 self.megabytes = self.MB = self / self._kB**2 self.gigabytes = self.GB = self / self._kB**3 self.petabytes = self.PB = self / self._kB**4 *suffixes, last = self._suffixes suffix = next(( suffix for suffix in suffixes if 1 < getattr(self, suffix) < self._kB ), last) self.readable = suffix, getattr(self, suffix) super().__init__() def __str__(self): return self.__format__('.2f') def __repr__(self): return '{}({})'.format(self.__class__.__name__, super().__repr__()) def __format__(self, format_spec): suffix, val = self.readable return '{val:{fmt}} {suf}'.format(val=math.ceil(val), fmt=format_spec, suf=suffix) def __sub__(self, other): return self.__class__(super().__sub__(other)) def __add__(self, other): return self.__class__(super().__add__(other)) def __mul__(self, other): return self.__class__(super().__mul__(other)) def __rsub__(self, other): return self.__class__(super().__sub__(other)) def __radd__(self, other): return self.__class__(super().__add__(other)) def __rmul__(self, other): return self.__class__(super().__rmul__(other))