// <auto-generated>
//  automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>

namespace MyGame.Example
{

using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;

public struct ArrayStruct : IFlatbufferObject
{
  private Struct __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); }
  public ArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public float A { get { return __p.bb.GetFloat(__p.bb_pos + 0); } }
  public void MutateA(float a) { __p.bb.PutFloat(__p.bb_pos + 0, a); }
  public int B(int j) { return __p.bb.GetInt(__p.bb_pos + 4 + j * 4); }
  public void MutateB(int j, int b) { __p.bb.PutInt(__p.bb_pos + 4 + j * 4, b); }
  public sbyte C { get { return __p.bb.GetSbyte(__p.bb_pos + 64); } }
  public void MutateC(sbyte c) { __p.bb.PutSbyte(__p.bb_pos + 64, c); }
  public MyGame.Example.NestedStruct D(int j) { return (new MyGame.Example.NestedStruct()).__assign(__p.bb_pos + 72 + j * 32, __p.bb); }
  public int E { get { return __p.bb.GetInt(__p.bb_pos + 136); } }
  public void MutateE(int e) { __p.bb.PutInt(__p.bb_pos + 136, e); }
  public long F(int j) { return __p.bb.GetLong(__p.bb_pos + 144 + j * 8); }
  public void MutateF(int j, long f) { __p.bb.PutLong(__p.bb_pos + 144 + j * 8, f); }

  public static Offset<MyGame.Example.ArrayStruct> CreateArrayStruct(FlatBufferBuilder builder, float A, int[] B, sbyte C, int[,] d_A, MyGame.Example.TestEnum[] d_B, MyGame.Example.TestEnum[,] d_C, long[,] d_D, int E, long[] F) {
    builder.Prep(8, 160);
    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
      builder.PutLong(F[_idx0-1]);
    }
    builder.Pad(4);
    builder.PutInt(E);
    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
      builder.Prep(8, 32);
      for (int _idx1 = 2; _idx1 > 0; _idx1--) {
        builder.PutLong(d_D[_idx0-1,_idx1-1]);
      }
      builder.Pad(5);
      for (int _idx1 = 2; _idx1 > 0; _idx1--) {
        builder.PutSbyte((sbyte)d_C[_idx0-1,_idx1-1]);
      }
      builder.PutSbyte((sbyte)d_B[_idx0-1]);
      for (int _idx1 = 2; _idx1 > 0; _idx1--) {
        builder.PutInt(d_A[_idx0-1,_idx1-1]);
      }
    }
    builder.Pad(7);
    builder.PutSbyte(C);
    for (int _idx0 = 15; _idx0 > 0; _idx0--) {
      builder.PutInt(B[_idx0-1]);
    }
    builder.PutFloat(A);
    return new Offset<MyGame.Example.ArrayStruct>(builder.Offset);
  }
  public ArrayStructT UnPack() {
    var _o = new ArrayStructT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(ArrayStructT _o) {
    _o.A = this.A;
    _o.B = new int[15];
    for (var _j = 0; _j < 15; ++_j) { _o.B[_j] = this.B(_j); }
    _o.C = this.C;
    _o.D = new MyGame.Example.NestedStructT[2];
    for (var _j = 0; _j < 2; ++_j) { _o.D[_j] = this.D(_j).UnPack(); }
    _o.E = this.E;
    _o.F = new long[2];
    for (var _j = 0; _j < 2; ++_j) { _o.F[_j] = this.F(_j); }
  }
  public static Offset<MyGame.Example.ArrayStruct> Pack(FlatBufferBuilder builder, ArrayStructT _o) {
    if (_o == null) return default(Offset<MyGame.Example.ArrayStruct>);
    var _b = _o.B;
    var _d_a = new int[2,2];
    for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_a[idx0,idx1] = _o.D[idx0].A[idx1];}}
    var _d_b = new MyGame.Example.TestEnum[2];
    for (var idx0 = 0; idx0 < 2; ++idx0) {_d_b[idx0] = _o.D[idx0].B;}
    var _d_c = new MyGame.Example.TestEnum[2,2];
    for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_c[idx0,idx1] = _o.D[idx0].C[idx1];}}
    var _d_d = new long[2,2];
    for (var idx0 = 0; idx0 < 2; ++idx0) {for (var idx1 = 0; idx1 < 2; ++idx1) {_d_d[idx0,idx1] = _o.D[idx0].D[idx1];}}
    var _f = _o.F;
    return CreateArrayStruct(
      builder,
      _o.A,
      _b,
      _o.C,
      _d_a,
      _d_b,
      _d_c,
      _d_d,
      _o.E,
      _f);
  }
};

public class ArrayStructT
{
  [Newtonsoft.Json.JsonProperty("a")]
  public float A { get; set; }
  [Newtonsoft.Json.JsonProperty("b")]
  public int[] B { get; set; }
  [Newtonsoft.Json.JsonProperty("c")]
  public sbyte C { get; set; }
  [Newtonsoft.Json.JsonProperty("d")]
  public MyGame.Example.NestedStructT[] D { get; set; }
  [Newtonsoft.Json.JsonProperty("e")]
  public int E { get; set; }
  [Newtonsoft.Json.JsonProperty("f")]
  public long[] F { get; set; }

  public ArrayStructT() {
    this.A = 0.0f;
    this.B = new int[15];
    this.C = 0;
    this.D = new MyGame.Example.NestedStructT[2];
    this.E = 0;
    this.F = new long[2];
  }
}


}
