예제 #1
0
def equals(attr_a, attr_b, synchronized_properties=test_properties):
    type_a = type(attr_a)
    type_b = type(attr_b)
    if type_a != type_b:
        return False

    if attr_a is None or is_builtin(type_a) or is_vector(type_a) or is_matrix(type_a):
        return attr_a == attr_b
    elif type_a == T.bpy_prop_array:
        return attr_a == attr_b
    elif issubclass(type_a, T.bpy_prop_collection):
        for key in attr_a.keys():
            attr_a_i = attr_a[key]
            attr_b_i = attr_b[key]
            if not equals(attr_a_i, attr_b_i):
                return False
    elif issubclass(type_a, T.bpy_struct):
        for name, _ in synchronized_properties.properties(attr_a.bl_rna):
            attr_a_i = getattr(attr_a, name)
            attr_b_i = getattr(attr_b, name)
            if not equals(attr_a_i, attr_b_i):
                return False
    else:
        raise TypeError("equals: Unexpected type {type_a}")

    return True
예제 #2
0
def equals(attr_a, attr_b, context=test_context):
    type_a = type(attr_a)
    type_b = type(attr_b)
    if type_a != type_b:
        return False

    if is_builtin(type_a) or is_vector(type_a) or is_matrix(type_a):
        if attr_a != attr_b:
            return False
    elif type_a == T.bpy_prop_array:
        if attr_a != attr_b:
            return False
    elif issubclass(type_a, T.bpy_prop_collection):
        for key in attr_a.keys():
            attr_a_i = attr_a[key]
            attr_b_i = attr_b[key]
            if not equals(attr_a_i, attr_b_i):
                return False
    elif issubclass(type_a, T.bpy_struct):
        for name, _ in context.properties(attr_a.bl_rna):
            attr_a_i = getattr(attr_a, name)
            attr_b_i = getattr(attr_b, name)
            if not equals(attr_a_i, attr_b_i):
                return False
    else:
        raise NotImplementedError

    return True
예제 #3
0
def bl_equals(attr_a, attr_b, msg=None, skip_name=False, context=None):
    """
    skip_name for the top level name only since cloned objects have different names
    """
    failureException = unittest.TestCase.failureException
    type_a = type(attr_a)
    type_b = type(attr_b)
    if type_a != type_b:
        raise failureException(f"Different types : {type_a} and {type_b}")
    if is_builtin(type_a) or is_vector(type_a) or is_matrix(type_a):
        if attr_a != attr_b:
            raise failureException(f"Different values : {attr_a} and {attr_b}")
    elif type_a == T.bpy_prop_array:
        if list(attr_a) != list(attr_b):
            raise failureException(
                f"Different values for array : {attr_a} and {attr_b}")
    elif issubclass(type_a, T.bpy_prop_collection):
        for key in attr_a.keys():
            attr_a_i = attr_a[key]
            attr_b_i = attr_b[key]
            try:
                equal = bl_equals(attr_a_i,
                                  attr_b_i,
                                  msg,
                                  skip_name=False,
                                  context=context)
            except failureException as e:
                raise failureException(
                    f'{e}\nDifferent values for collection items at key "{key}" : {attr_a_i} and {attr_b_i}'
                ) from None
            if not equal:
                raise failureException(
                    f'Different values for collection items at key "{key}" : {attr_a_i} and {attr_b_i}'
                )

    elif issubclass(type_a, T.bpy_struct):
        for name, _ in context.properties(attr_a.bl_rna):
            if skip_name and (name == "name" or name == "name_full"):
                continue
            attr_a_i = getattr(attr_a, name)
            attr_b_i = getattr(attr_b, name)
            try:
                equal = bl_equals(attr_a_i,
                                  attr_b_i,
                                  msg,
                                  skip_name=False,
                                  context=context)
            except failureException as e:
                raise failureException(
                    f'{e}\nDifferent values for struct items at key "{name}" : {attr_a_i} and {attr_b_i}'
                ) from None
            if not equal:
                raise failureException(
                    f'Different values for struct items at key "{name}" : {attr_a_i} and {attr_b_i}'
                )

    else:
        raise NotImplementedError

    return True
예제 #4
0
    def array_attr(self, aos: T.bpy_prop_collection, member_name: str, bl_rna: T.bpy_struct):
        prototype_item = getattr(aos[0], member_name)
        member_type = type(prototype_item)

        if is_vector(member_type):
            array_size = len(aos) * len(prototype_item)
        elif member_type is T.bpy_prop_array:
            member_type = type(prototype_item[0])
            if isinstance(bl_rna, T.MeshPolygon) and member_name == "vertices":
                # polygon sizes can differ
                array_size = sum((len(polygon.vertices) for polygon in aos))
            else:
                array_size = len(aos) * len(prototype_item)
        else:
            array_size = len(aos)

        return array_size, member_type
예제 #5
0
def read_attribute(attr: Any, key: Union[int, str], attr_property: T.Property,
                   context: Context):
    """
    Load a property into a python object of the appropriate type, be it a Proxy or a native python object
    """
    attr_type = type(attr)

    if is_builtin(attr_type):
        return attr
    if is_vector(attr_type):
        return list(attr)
    if is_matrix(attr_type):
        return [list(col) for col in attr.col]

    # We have tested the types that are usefully reported by the python binding, now harder work.
    # These were implemented first and may be better implemented with the bl_rna property of the parent struct
    # TODO flatten
    if attr_type == T.bpy_prop_array:
        return list(attr)

    try:
        context.visit_state.recursion_guard.push(attr_property.identifier)
        if attr_type == T.bpy_prop_collection:
            if isinstance(attr_property.fixed_type, bpy.types.ID):
                from mixer.blender_data.datablock_collection_proxy import DatablockRefCollectionProxy

                return DatablockRefCollectionProxy().load(attr, key, context)
            elif is_soable_collection(attr_property):
                from mixer.blender_data.aos_proxy import AosProxy

                return AosProxy().load(attr, key, attr_property, context)
            else:
                from mixer.blender_data.struct_collection_proxy import StructCollectionProxy

                return StructCollectionProxy.make(attr_property).load(
                    attr, key, attr_property, context)

        # TODO merge with previous case
        if isinstance(attr_property, T.CollectionProperty):
            from mixer.blender_data.struct_collection_proxy import StructCollectionProxy

            return StructCollectionProxy().load(attr, key, attr_property,
                                                context)

        bl_rna = attr_property.bl_rna
        if bl_rna is None:
            logger.warning("Not implemented: attribute %s", attr)
            return None

        if issubclass(attr_type, T.PropertyGroup):
            from mixer.blender_data.struct_proxy import StructProxy

            return StructProxy().load(attr, key, context)

        if issubclass(attr_type, T.ID):
            if attr.is_embedded_data:
                from mixer.blender_data.datablock_proxy import DatablockProxy

                return DatablockProxy.make(attr_property).load(
                    attr, key, context)
            else:
                from mixer.blender_data.datablock_ref_proxy import DatablockRefProxy

                return DatablockRefProxy().load(attr, key, context)

        if issubclass(attr_type, T.bpy_struct):
            from mixer.blender_data.struct_proxy import StructProxy

            return StructProxy().load(attr, key, context)

        if attr is None and isinstance(attr_property, T.PointerProperty):
            from mixer.blender_data.misc_proxies import NonePtrProxy

            return NonePtrProxy()

        logger.error(
            f"Unsupported attribute {attr_type} {attr_property} {attr_property.fixed_type} at {context.visit_state.datablock_proxy._class_name}.{context.visit_state.path}.{attr_property.identifier}"
        )
    finally:
        context.visit_state.recursion_guard.pop()