Package com.mtbs3d.minecrift

Source Code of com.mtbs3d.minecrift.MCHydra

/**
* Copyright 2013 Mark Browning, StellaArtois
* Licensed under the LGPL 3.0 or later (See LICENSE.md for details)
*/
package com.mtbs3d.minecrift;

import java.io.File;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;

import com.mtbs3d.minecrift.api.*;
import com.mtbs3d.minecrift.control.ControlBinding;
import com.mtbs3d.minecrift.settings.VRSettings;
import com.sixense.utils.enums.EnumControllerDesc;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;

import com.sixense.ControllerData;
import com.sixense.EnumButton;
import com.sixense.Sixense;
import com.sixense.utils.ControllerManager;
import com.sixense.utils.enums.EnumSetupStep;

import net.minecraft.src.Minecraft;
import net.minecraft.src.EntityClientPlayerMP;
import net.minecraft.src.GameSettings;
import net.minecraft.src.MathHelper;
import net.minecraft.src.Vec3;
import org.lwjgl.util.vector.Quaternion;
import org.lwjgl.util.vector.Vector4f;

/**
* @author Mark Browning
*
*/
public class MCHydra extends BasePlugin implements ICenterEyePositionProvider, IOrientationProvider, IBodyAimController, IEventListener {

    ControllerManager cm;
    public static ControllerData[] newData = {new ControllerData(), new ControllerData(), new ControllerData(), new ControllerData()};

    Vec3 headPos; //in meters, in world coordinates
    Vec3 origin = Vec3.createVectorHelper(0, 0, 0)//in meters, relative to hydra base station

    public final float[] IDENTITY_QUAT = {0.0f, 0.0f, 0.0f, 1.0f};   // x, y, z, w

    float baseStationYawOffset = 0.0f;

    boolean hydraRunning = false;
  private boolean hydraInitialized = false;
  private String initStatus = "";
  private String calibrationStep = "";

  private static boolean libraryLoaded = false;
 
    private boolean resetOrigin = true;
    private boolean resetOriginRotation = true;

  //latest data
 
  private float cont1PosX = 0;
  private float cont1PosY = 0;
  private float cont1PosZ = 0;
  private float cont2PosX = 0;
  private float cont2PosY = 0;
  private float cont2PosZ = 0;

  private float cont1Yaw = 0;
  private float cont1Pitch = 0;
  private float cont1Roll = 0;
    private float[] cont1OrientationQuat_xyzw = IDENTITY_QUAT;

  private float cont2Yaw = 0;
  private float cont2Pitch = 0;
  private float cont2Roll = 0;
    private float[] cont2OrientationQuat_xyzw = IDENTITY_QUAT;
 
  //For IOrientationProvider implementation; allows setting origin to set yaw offset as well
  private float yawOffset = 0;


    private final float SCALE = 0.001f; //mm -> m
    private float userScale = SCALE;

    // Previously +X 1.0f, -Y -1.0f, +Z 1.0f
    private final float XDIRECTION = 1.0f;    // +X
    private final float YDIRECTION = 1.0f;    // +Y
    private final float ZDIRECTION = 1.0f;    // +Z
   
    //body/Aim implementation
    private float bodyYaw = 0; //floating; not fixed to base station;
    private float aimYaw = 0; //relative to bodyYaw, so that IRL "forward"
    //(that is, baseStationYawOffset) is always the direction of movement

    //aimPitch is always cont2Pitch

    //Input/controller
  int lastcont1Buttons = 0;
  int lastcont2Buttons = 0;
 
  //For mouse menu emulation
  private int hydraMouseX = 0;
  private int hydraMouseY = 0;
  private boolean leftMouseClicked = false;
  private Field keyDownField; //Whee, reflection
  private Field buttonDownField; //Whee, reflection
  private boolean mouseUseJoystick = true;
 

  public MCHydra()
  {
    super();
        pluginID = "hydra";
        pluginName = "Razer Hydra";

  }
  @Override
  public String getInitializationStatus() {
    return initStatus;
  }

  @Override
  public String getVersion() {
    return "0.28";
  }

  @Override
  public boolean init(File nativeDir) {
    hydraInitialized = libraryLoaded;

    if( !libraryLoaded )
    {
      try {
        libraryLoaded = Sixense.LoadLibrary(nativeDir);
      }
      catch( UnsatisfiedLinkError e )
      {
        initStatus = e.getMessage();
      }
    }

    if( libraryLoaded )
    {
      init();
    }
    return hydraInitialized;
  }

  @Override
  public boolean init() {
    Sixense.init();
    cm = ControllerManager.getInstance();
    cm.setGameType(com.sixense.utils.enums.EnumGameType.ONE_PLAYER_TWO_CONTROLLER);
    Sixense.setActiveBase(0);
    Sixense.setFilterEnabled(Minecraft.getMinecraft().vrSettings.hydraUseFilter);
   
        try {
      keyDownField = Keyboard.class.getDeclaredField("keyDownBuffer");
      keyDownField.setAccessible(true);
      buttonDownField = Mouse.class.getDeclaredField("buttons");
      buttonDownField.setAccessible(true);
    } catch (SecurityException e) {
    } catch (NoSuchFieldException e) {
    }

    hydraInitialized = true;
    return isInitialized(); //no re-init method
  }

  @Override
  public boolean isInitialized() {
    return hydraInitialized;
  }
 
  @Override
  public void poll(float delta)
    {
        if (!isInitialized())
            return;

        Minecraft mc = Minecraft.getMinecraft();

        // Poll hydras; get orientation, and position information in metres
        Sixense.getAllNewestData(newData);

        // Update the controller manager, allowing us to determine which
        // controller is the 'Left' controller, and which is the 'Right'
        // (if calibrated)
        cm.update(newData);
        int leftIndex = cm.getIndex(EnumControllerDesc.P1L);
        int rightIndex = cm.getIndex(EnumControllerDesc.P1R);

        ControllerData cont1, cont2;
        if (leftIndex != -1 && rightIndex != -1)
        {
            if (mc.vrSettings.posTrackHydraUseController1)
            {
                cont1 = newData[leftIndex];
                cont2 = newData[rightIndex];
            }
            else
            {
                cont1 = newData[rightIndex];
                cont2 = newData[leftIndex];
            }
        }
        else
        {
            // Not yet calibrated
            cont1 = newData[0];
            cont2 = newData[1];
        }

        EnumSetupStep step = cm.getCurrentStep();
        switch ( step )
        {
            case P1C2_IDLE:
                hydraRunning = true;
                calibrationStep = "";
                break;
            default:
                hydraRunning = false;
                if (step != null)
                {
                    //System.out.println("HYDRA: " + step.toString());
                    calibrationStep = cm.getStepString();
                }
                break;
        }

        if (hydraRunning)
        {
            cont1Yaw   = cont1.yaw;
            cont1Pitch = cont1.pitch;
            cont1Roll  = cont1.roll;
            cont1OrientationQuat_xyzw = cont1.rot_quat;

            cont2Yaw   = cont2.yaw;
            cont2Pitch = cont2.pitch;
            cont2Roll  = cont2.roll;
            cont2OrientationQuat_xyzw = cont2.rot_quat;
        }
        else
        {
            cont1Yaw   = 0;
            cont1Pitch = 0;
            cont1Roll  = 0;
            cont1OrientationQuat_xyzw = IDENTITY_QUAT;

            cont2Yaw   = 0;
            cont2Pitch = 0;
            cont2Roll  = 0;
            cont2OrientationQuat_xyzw = IDENTITY_QUAT;
        }

        userScale = SCALE * mc.vrSettings.posTrackHydraDistanceScale;

        cont1PosX = userScale * cont1.pos[0] * XDIRECTION;
        cont1PosY = userScale * cont1.pos[1] * YDIRECTION;
        cont1PosZ = userScale * cont1.pos[2] * ZDIRECTION;

        cont2PosX = userScale * cont2.pos[0] * XDIRECTION;
        cont2PosY = userScale * cont2.pos[1] * YDIRECTION;
        cont2PosZ = userScale * cont2.pos[2] * ZDIRECTION;

        if( mc.lookaimController != this) return;
        if( mc.theWorld != null )
        {
          EntityClientPlayerMP thePlayer = mc.thePlayer;
         
          //buttons?
          //TODO: move this somewhere sane and make configurable
          GameSettings settings = mc.gameSettings;
 
          if((cont2.buttons & EnumButton.START.mask())>0 &&
            (lastcont2Buttons & EnumButton.START.mask()) == 0)
          {
            if(mc.currentScreen != null)
              thePlayer.closeScreen();
            else
              settings.keyBindInventory.pressTime=1;
          }

          if((cont1.buttons & EnumButton.START.mask())>0 &&
            (lastcont1Buttons & EnumButton.START.mask()) == 0)
          {
            if(mc.currentScreen != null)
              thePlayer.closeScreen();
            else
              mc.displayInGameMenu();
          }
        
          //In game!
          if( mc.currentScreen == null )
          {
            hydraMouseX = 0;
            hydraMouseY = 0;

            //aim/body adjustments
            float headYaw = 0;
            if( mc.vrSettings.keyholeHeadRelative )
              headYaw = mc.headTracker.getHeadYawDegrees();
           
            //Adjust keyhole width on controller pitch; otherwise its a very narrow window at the top and bottom
            float keyholeYaw = mc.vrSettings.aimKeyholeWidthDegrees/2/MathHelper.cos(cont2Pitch*PIOVER180);
           
            float bodyYawT = cont2Yaw - baseStationYawOffset; //

              if( bodyYawT > headYaw + keyholeYaw  )
              {
                bodyYawT = Math.min(10,bodyYawT - headYaw - keyholeYaw) * 0.1f*mc.vrSettings.joystickSensitivity; //TODO: add new sensitivity
                //Controller pointing too far right, move body to the right
                  aimYaw = headYaw + keyholeYaw;
              }
              else if( bodyYawT < headYaw -keyholeYaw )
              {
                //Controller pointing too far left, move body to the left
                bodyYawT = Math.max(-10,bodyYawT -headYaw + keyholeYaw) * 0.1f*mc.vrSettings.joystickSensitivity;
                  aimYaw = headYaw - keyholeYaw;
              }
              else
              {
                aimYaw = bodyYawT;
                bodyYawT = 0;
              }
              bodyYaw += bodyYawT;
                bodyYaw %= 360;
           
            if( thePlayer != null )
            {
              if( Math.abs(cont2.joystick_y)>0.01)
                thePlayer.movementInput.baseMoveForward = cont2.joystick_y;
              else
                thePlayer.movementInput.baseMoveForward = 0.0f;
             
              if( Math.abs(cont2.joystick_x)>0.01)
                thePlayer.movementInput.baseMoveStrafe = -cont2.joystick_x;
              else
                thePlayer.movementInput.baseMoveStrafe = 0.0f;
            }
   
            //Do buttons
            if( cont2.trigger > 0.05 )
            {
              if( !leftMouseClicked )
                mc.clickMouse(0);
              settings.keyBindAttack.pressed = true;
              leftMouseClicked = true;
            }
            else
            {
              leftMouseClicked = false;
              settings.keyBindAttack.pressed = false;
            }
             
            if((cont2.buttons & EnumButton.BUMPER.mask()) >0 &&
               (lastcont2Buttons & EnumButton.BUMPER.mask()) == 0)
            {
              mc.clickMouse(1);
            }

            settings.keyBindUseItem.pressed = (cont2.buttons & EnumButton.BUMPER.mask()) >0 ;
           
            if((cont2.buttons & EnumButton.JOYSTICK.mask())>0 &&
               (lastcont2Buttons & EnumButton.JOYSTICK.mask()) == 0)
            {
              settings.keyBindSneak.pressed = true;
            }
            if(( lastcont2Buttons   & EnumButton.JOYSTICK.mask())>0 &&
              (cont2.buttons & EnumButton.JOYSTICK.mask()) == 0)
            {
              settings.keyBindSneak.pressed = false;
            }
 
            if((cont2.buttons & EnumButton.BUTTON_1.mask())>0 &&
              (lastcont2Buttons & EnumButton.BUTTON_1.mask()) == 0)
            {
              settings.keyBindDrop.pressTime++;
            }
 
            if((cont2.buttons & EnumButton.BUTTON_2.mask())>0 &&
              (lastcont2Buttons & EnumButton.BUTTON_2.mask()) == 0)
            {
              settings.keyBindJump.pressed = true;
            }
            if((lastcont2Buttons & EnumButton.BUTTON_2.mask())>0 &&
              (cont2.buttons & EnumButton.BUTTON_2.mask()) == 0)
            {
              settings.keyBindJump.pressed = false;
            }
           
            if((cont2.buttons & EnumButton.BUTTON_3.mask())>0 &&
              (lastcont2Buttons & EnumButton.BUTTON_3.mask()) == 0)
            {
              thePlayer.inventory.changeCurrentItem(1);
            }
   
            if((cont2.buttons & EnumButton.BUTTON_4.mask())>0 &&
              (lastcont2Buttons & EnumButton.BUTTON_4.mask()) == 0)
            {
              thePlayer.inventory.changeCurrentItem(-1);
            }
          }
        }
       
        //GUI controls
        if( mc.currentScreen != null )
        {
          mouseUseJoystick = false;
          if( mouseUseJoystick )
          {
            hydraMouseX += 2*mc.vrSettings.joystickSensitivity*cont2.joystick_x;
            hydraMouseY += 2*mc.vrSettings.joystickSensitivity*cont2.joystick_y;
          }
          else
          {
            hydraMouseX = (int)(mc.displayWidth * 0.5*cont2Yaw/75f   ));
            hydraMouseY = (int)(mc.displayWidth * ( -0.5*cont2Pitch/60f ));
          }
            float scaleX = mc.displayFBWidth/(float)mc.displayWidth;
            float scaleY = mc.displayFBHeight/(float)mc.displayHeight;
            mc.currentScreen.mouseOffsetX = (int)(hydraMouseX*scaleX);
            mc.currentScreen.mouseOffsetY = (int)(hydraMouseY*scaleY);
          int mouseX = Mouse.getX() + hydraMouseX;
          int  mouseY = Mouse.getY() + hydraMouseY;
            Mouse.setCursorPosition(mouseX, mouseY);
           
            mouseX = (int)(mouseX*scaleX);
            mouseY = (int)(mouseY*scaleY);

            //hack, hack hack... Joystick button is right shift for use in GUI
            //Set the internal keyboard state that right shift is depressed if this button is
          if( keyDownField != null )
          {
            try {
              byte b = (byte)((cont2.buttons & EnumButton.JOYSTICK.mask())>0?1:0);
          ((ByteBuffer)keyDownField.get(null)).put(Keyboard.KEY_RSHIFT,b);
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
          }

          if( cont2.trigger > 0.05 )
          {
            //click left mouse button
            if(!leftMouseClicked)
              mc.currentScreen.mouseDown(mouseX,mouseY,0);
            else
              //Already down
              mc.currentScreen.mouseDrag(mouseX, mouseY);//Signals mouse move
            leftMouseClicked = true;
            if( buttonDownField != null )
            {
              try {
            ((ByteBuffer)buttonDownField.get(null)).put(0,(byte) 1);
          } catch (IllegalArgumentException e) {
          } catch (IllegalAccessException e) {
          }
            }
          }
          else if( leftMouseClicked )
          {
            mc.currentScreen.mouseUp(mouseX,mouseY,0);
            leftMouseClicked = false;
          }

          if((cont2.buttons & EnumButton.BUMPER.mask())>0 )
          {
            if ((lastcont2Buttons & EnumButton.BUMPER.mask()) == 0)
              mc.currentScreen.mouseDown(mouseX,mouseY,1);
            else
              mc.currentScreen.mouseDrag(mouseX, mouseY);
            if( buttonDownField != null )
            {
              try {
            ((ByteBuffer)buttonDownField.get(null)).put(1,(byte) 1);
          } catch (IllegalArgumentException e) {
          } catch (IllegalAccessException e) {
          }
            }
          }
          else if( ( lastcont2Buttons & EnumButton.BUMPER.mask())>0 )
          {
            mc.currentScreen.mouseUp(mouseX,mouseY,1);
          }
         
        }

        lastcont1Buttons = cont1.buttons;
        lastcont2Buttons = cont2.buttons;
  }

  @Override
  public void destroy() {
    Sixense.exit();
        hydraRunning = false;
        hydraInitialized = false;
        initStatus = "Not initialised";
        cm = null;
  }

  @Override
  public void update(float yawHeadDegrees, float pitchHeadDegrees, float rollHeadDegrees,
                       float worldYawOffsetDegrees, float worldPitchOffsetDegrees, float worldRollOffsetDegrees)
    {
        if (!hydraInitialized)
        {
          headPos = Vec3.createVectorHelper(0, 0, 0);
            return;
        }

        VRSettings vrSettings = Minecraft.getMinecraft().vrSettings;
       
        if( resetOriginRotation )
        {
          //TODO: this might be backwards: with only a razer to test the yawHeadDegrees, its always the same!
          if( Minecraft.getMinecraft().headTracker != this ) //if the positional tracker is the hydra, they are always aligned
          {
            baseStationYawOffset = cont1Yaw - yawHeadDegrees; //assume hydra oriented straight with head orientation
            if( vrSettings.posTrackHydraLoc == vrSettings.POS_TRACK_HYDRA_LOC_BACK_OF_HEAD)   // TODO: Also needed for HMD top?
                {
                    //assume hydra oriented at 90degrees to head orientation
              if (vrSettings.posTrackHydraBIsPointingLeft)
                    {
                        baseStationYawOffset -= 90;
                    }
                    else
                    {
                        baseStationYawOffset += 90;
                    }
                }
          }
          resetOriginRotation = false;
        }
       

        // Using a single controller. Select controller. poll() has already switch left and right depending on configuration
        //cont1 is for head tracking, if head tracking is enabled (TODO: make head tracking optional?)
        float rawX = cont1PosX;
        float rawY = cont1PosY;
        float rawZ = cont1PosZ;

        if (vrSettings.posTrackHydraLoc == vrSettings.POS_TRACK_HYDRA_LOC_HMD_LEFT_AND_RIGHT)
        {
          //Otherwise, use average of controllers
            rawX = (cont1PosX + cont2PosX) / 2.0f;
            rawY = (cont1PosY + cont2PosY) / 2.0f;
            rawZ = (cont1PosZ + cont2PosZ) / 2.0f;
        }

        // Correct for distance from base y axis skew
        // TODO: figure out why the heck this is required for Stella's Hydras...
        // TODO: rename this gameSetting to "hydraXRotationSkew" or other sensible name
        rawY += rawZ * MathHelper.sin(vrSettings.posTrackHydraYAxisDistanceSkewAngleDeg*PIOVER180 );
       
        //Raw is the absolute coordinate in hydra reference frame of the sample (possible average of two controllers)
        Vec3 raw = Vec3.createVectorHelper(rawX, rawY, rawZ);
       
        //Rel is the relative coordinate in hydra reference frame
        Vec3 rel = origin.subtract(raw);
       
        //Account for hydra base station / head tracker orientation not aligned
        //After this, rel is in body coordinates (relative to head tracker reference frame, not accounting for mouse-induced world yaw offset)
        rel.rotateAroundY(baseStationYawOffset*PIOVER180);

        //Now, compute the offset from the hydra controller to the camera location. Straight from the settings (although negated -
        //vrSettings stores eye center -> hydra values for user readability. We need hydra -> eye center values here)
        float hydraXOffset = -vrSettings.getPosTrackHydraOffsetX();
        float hydraYOffset = -vrSettings.getPosTrackHydraOffsetY();
        float hydraZOffset = vrSettings.getPosTrackHydraOffsetZ();

        // The configured offset is for a 0,0,0 rotation head. Apply current head orientation to get final offset
        Vec3 correctionToCentreEyePosition = Vec3.createVectorHelper(hydraXOffset, hydraYOffset, hydraZOffset);

        correctionToCentreEyePosition.rotateAroundZ(rollHeadDegrees*PIOVER180);
        correctionToCentreEyePosition.rotateAroundX(pitchHeadDegrees*PIOVER180);
        correctionToCentreEyePosition.rotateAroundY(-yawHeadDegrees*PIOVER180);

        //Add the hydra position (in head tracker reference frame) to the camera offset
        //to get the camera position in head tracker reference frame
        headPos = vecAdd(rel,correctionToCentreEyePosition);

        if (resetOrigin)
        {
          //We compute the "ideal" neck model position, in head tracker reference frame
          Vec3 neckModelToCentreEyePosition = Vec3.createVectorHelper(0, vrSettings.neckBaseToEyeHeight, -vrSettings.eyeProtrusion);
          neckModelToCentreEyePosition.rotateAroundZ(rollHeadDegrees*PIOVER180);
          neckModelToCentreEyePosition.rotateAroundX(pitchHeadDegrees*PIOVER180);
          neckModelToCentreEyePosition.rotateAroundY(-yawHeadDegrees*PIOVER180);

          //The actual hydra position on the head is offset from the eye center by this amount
          Vec3 originOffset = correctionToCentreEyePosition.subtract(neckModelToCentreEyePosition);
       
          //Counteract the base station yaw to get back to absolute razer coordinates
          originOffset.rotateAroundY(-baseStationYawOffset*PIOVER180);

            // save raw - originOffset as origin. That way, when origin is subtracted in the future,
          // positions very close to the current location+orientation will have the eye in the correct spot
          origin = originOffset.subtract(raw);
           
            resetOrigin = false;
        }

        // Rotate the centre eye position around any world yaw offset (mouse/controller induced rotation)
        headPos.rotateAroundY(-worldYawOffsetDegrees*PIOVER180);

        //System.out.println(String.format("Positional Track: (l/r)x=%.3fcm, (up/down)y=%.3fcm, (in/out)z=%.3fcm", new Object[] {Float.valueOf((float)headPos.xCoord * 100.0f), Float.valueOf((float)headPos.yCoord * 100.0f), Float.valueOf((float)headPos.zCoord * 100.0f)}));
  }

    @Override
  public Vec3 getCenterEyePosition() {
    return headPos;
  }

  @Override
  public void resetOrigin() {
    resetOrigin = true;
  }

    @Override
  public void resetOriginRotation() {
    resetOriginRotation = true;

        Minecraft mc = Minecraft.getMinecraft();
        if( resetOriginRotation && mc.headTracker == this )
        {
          float prevTotalYaw = mc.lookaimController.getBodyYawDegrees() + getHeadYawDegrees();
          yawOffset = cont1Yaw;
          if( mc.thePlayer == null )
            //Reset bodyYaw for main menu
            mc.lookaimController.setBodyYawDegrees(0);
          else
            mc.lookaimController.setBodyYawDegrees(prevTotalYaw);
        }

  }

  @Override
  public void setPrediction(float delta, boolean enable) {
        Sixense.setFilterEnabled(enable);
  }

  @Override
  public float getHeadYawDegrees() {
    return cont1Yaw - yawOffset;
  }

  @Override
  public float getHeadPitchDegrees() {
    return cont1Pitch;
  }

  @Override
  public float getHeadRollDegrees() {
    return cont1Roll;
  }

    @Override
    public Quaternion getOrientationQuaternion()
    {
        // Needs x, y, z, w
        Quaternion orientation   = new Quaternion(cont1OrientationQuat_xyzw[0],
                cont1OrientationQuat_xyzw[1], cont1OrientationQuat_xyzw[2], cont1OrientationQuat_xyzw[3]);

        // Apply yaw offset
        Quaternion yaw           = new Quaternion();
        Vector4f vecAxisYawAngle = new Vector4f(0f, 1f, 0f, -yawOffset * PIOVER180);
        yaw.setFromAxisAngle(vecAxisYawAngle);
        Quaternion.mul(yaw, orientation, orientation);
        return orientation;
    }

  @Override
  public void beginAutomaticCalibration() {
    resetOriginRotation(); //Reset the head tracker/hydra orientation reference frame
  }

  @Override
  public void updateAutomaticCalibration() {/*no-op*/ }

  @Override
  public float getBodyYawDegrees() {
    return bodyYaw;
  }

  @Override
  public void setBodyYawDegrees(float yawOffset) {
    bodyYaw = yawOffset;
  }

  @Override
  public float getBodyPitchDegrees() {
    return 0; //Always return 0 for body pitch
  }

  @Override
  public float getAimYaw() {
    return aimYaw + bodyYaw;
  }
  @Override
  public float getAimPitch() {
    return cont2Pitch;
  }

  @Override
  public boolean isCalibrated() {
    return hydraRunning;
  }

  @Override
  public String getCalibrationStep() {
    return calibrationStep;
  }
 
  Vec3 vecAdd(Vec3 a, Vec3 b)
  {
    return a.addVector(b.xCoord, b.yCoord, b.zCoord);
  }

    @Override
    public void eventNotification(int eventId)
    {
        if (eventId == IBasePlugin.EVENT_CALIBRATION_SET_ORIGIN)
        {
            resetOrigin();
            resetOriginRotation();
        }
    }
  @Override
  public void mapBinding(ControlBinding binding) {
    // TODO Auto-generated method stub
   
  }
}
TOP

Related Classes of com.mtbs3d.minecrift.MCHydra

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.