// automatically generated by the FlatBuffers compiler, do not modify

package MyGame.Example;

import com.google.flatbuffers.BaseVector;
import com.google.flatbuffers.BooleanVector;
import com.google.flatbuffers.ByteVector;
import com.google.flatbuffers.Constants;
import com.google.flatbuffers.DoubleVector;
import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.FloatVector;
import com.google.flatbuffers.IntVector;
import com.google.flatbuffers.LongVector;
import com.google.flatbuffers.ShortVector;
import com.google.flatbuffers.StringVector;
import com.google.flatbuffers.Struct;
import com.google.flatbuffers.UnionVector;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

@SuppressWarnings("unused")
public final class Vec3 extends Struct {
  public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
  public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public float x() { return bb.getFloat(bb_pos + 0); }
  public void mutateX(float x) { bb.putFloat(bb_pos + 0, x); }
  public float y() { return bb.getFloat(bb_pos + 4); }
  public void mutateY(float y) { bb.putFloat(bb_pos + 4, y); }
  public float z() { return bb.getFloat(bb_pos + 8); }
  public void mutateZ(float z) { bb.putFloat(bb_pos + 8, z); }
  public double test1() { return bb.getDouble(bb_pos + 16); }
  public void mutateTest1(double test1) { bb.putDouble(bb_pos + 16, test1); }
  public int test2() { return bb.get(bb_pos + 24) & 0xFF; }
  public void mutateTest2(int test2) { bb.put(bb_pos + 24, (byte) test2); }
  public MyGame.Example.Test test3() { return test3(new MyGame.Example.Test()); }
  public MyGame.Example.Test test3(MyGame.Example.Test obj) { return obj.__assign(bb_pos + 26, bb); }

  public static int createVec3(FlatBufferBuilder builder, float x, float y, float z, double test1, int test2, short test3_a, byte test3_b) {
    builder.prep(8, 32);
    builder.pad(2);
    builder.prep(2, 4);
    builder.pad(1);
    builder.putByte(test3_b);
    builder.putShort(test3_a);
    builder.pad(1);
    builder.putByte((byte) test2);
    builder.putDouble(test1);
    builder.pad(4);
    builder.putFloat(z);
    builder.putFloat(y);
    builder.putFloat(x);
    return builder.offset();
  }

  public static final class Vector extends BaseVector {
    public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; }

    public Vec3 get(int j) { return get(new Vec3(), j); }
    public Vec3 get(Vec3 obj, int j) {  return obj.__assign(__element(j), bb); }
  }
  public Vec3T unpack() {
    Vec3T _o = new Vec3T();
    unpackTo(_o);
    return _o;
  }
  public void unpackTo(Vec3T _o) {
    float _oX = x();
    _o.setX(_oX);
    float _oY = y();
    _o.setY(_oY);
    float _oZ = z();
    _o.setZ(_oZ);
    double _oTest1 = test1();
    _o.setTest1(_oTest1);
    int _oTest2 = test2();
    _o.setTest2(_oTest2);
    test3().unpackTo(_o.getTest3());
  }
  public static int pack(FlatBufferBuilder builder, Vec3T _o) {
    if (_o == null) return 0;
    short _test3_a = _o.getTest3().getA();
    byte _test3_b = _o.getTest3().getB();
    return createVec3(
      builder,
      _o.getX(),
      _o.getY(),
      _o.getZ(),
      _o.getTest1(),
      _o.getTest2(),
      _test3_a,
      _test3_b);
  }
}

