# automatically generated by the FlatBuffers compiler, do not modify

# namespace: Example

import flatbuffers
from flatbuffers.compat import import_numpy
np = import_numpy()

class StructOfStructs(object):
    __slots__ = ['_tab']

    @classmethod
    def SizeOf(cls):
        return 20

    # StructOfStructs
    def Init(self, buf, pos):
        self._tab = flatbuffers.table.Table(buf, pos)

    # StructOfStructs
    def A(self, obj):
        obj.Init(self._tab.Bytes, self._tab.Pos + 0)
        return obj

    # StructOfStructs
    def B(self, obj):
        obj.Init(self._tab.Bytes, self._tab.Pos + 8)
        return obj

    # StructOfStructs
    def C(self, obj):
        obj.Init(self._tab.Bytes, self._tab.Pos + 12)
        return obj


def CreateStructOfStructs(builder, a_id, a_distance, b_a, b_b, c_id, c_distance):
    builder.Prep(4, 20)
    builder.Prep(4, 8)
    builder.PrependUint32(c_distance)
    builder.PrependUint32(c_id)
    builder.Prep(2, 4)
    builder.Pad(1)
    builder.PrependInt8(b_b)
    builder.PrependInt16(b_a)
    builder.Prep(4, 8)
    builder.PrependUint32(a_distance)
    builder.PrependUint32(a_id)
    return builder.Offset()

import MyGame.Example.Ability
import MyGame.Example.Test
try:
    from typing import Optional
except:
    pass

class StructOfStructsT(object):

    # StructOfStructsT
    def __init__(self):
        self.a = None  # type: Optional[MyGame.Example.Ability.AbilityT]
        self.b = None  # type: Optional[MyGame.Example.Test.TestT]
        self.c = None  # type: Optional[MyGame.Example.Ability.AbilityT]

    @classmethod
    def InitFromBuf(cls, buf, pos):
        structOfStructs = StructOfStructs()
        structOfStructs.Init(buf, pos)
        return cls.InitFromObj(structOfStructs)

    @classmethod
    def InitFromObj(cls, structOfStructs):
        x = StructOfStructsT()
        x._UnPack(structOfStructs)
        return x

    # StructOfStructsT
    def _UnPack(self, structOfStructs):
        if structOfStructs is None:
            return
        if structOfStructs.A(MyGame.Example.Ability.Ability()) is not None:
            self.a = MyGame.Example.Ability.AbilityT.InitFromObj(structOfStructs.A(MyGame.Example.Ability.Ability()))
        if structOfStructs.B(MyGame.Example.Test.Test()) is not None:
            self.b = MyGame.Example.Test.TestT.InitFromObj(structOfStructs.B(MyGame.Example.Test.Test()))
        if structOfStructs.C(MyGame.Example.Ability.Ability()) is not None:
            self.c = MyGame.Example.Ability.AbilityT.InitFromObj(structOfStructs.C(MyGame.Example.Ability.Ability()))

    # StructOfStructsT
    def Pack(self, builder):
        return CreateStructOfStructs(builder, self.a.id, self.a.distance, self.b.a, self.b.b, self.c.id, self.c.distance)
