/*******************************************************************************
* Copyright 2013 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.worldwind.common.input.hydra;
import com.sixense.ControllerData;
import com.sixense.Sixense;
import com.sixense.SixenseActivator;
import com.sixense.utils.ControllerManager;
import com.sixense.utils.enums.EnumGameType;
import com.sixense.utils.enums.EnumSetupStep;
/**
* Singleton that handles Razer Hydra input. Uses SixenseJava library.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class Hydra
{
private static final Hydra INSTANCE = new Hydra();
public static Hydra getInstance()
{
return INSTANCE;
}
private final int POLLING_DELAY = 50; //ms
private final int FINDING_DELAY = 1000; //ms
private final ControllerData[] data = { new ControllerData(), new ControllerData(), new ControllerData(),
new ControllerData() };
private final HydraListenerList listeners = new HydraListenerList();
private int lastButton1;
private int lastButton2;
private HydraStickEvent lastStickEvent = new HydraStickEvent();
private HydraTriggerEvent lastTriggerEvent = new HydraTriggerEvent();
private Hydra()
{
if (!loadLibrary())
{
return;
}
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
if (Sixense.init())
{
Sixense.setActiveBase(0);
final ControllerManager cm = ControllerManager.getInstance();
cm.setGameType(EnumGameType.ONE_PLAYER_ONE_CONTROLLER);
while (true)
{
cm.update(data);
EnumSetupStep step = cm.getCurrentStep();
//enum equality doesn't work here?! what?
if (step.ordinal() == EnumSetupStep.P1C1_POWER_UP_0.ordinal())
{
startPolling();
break;
}
try
{
Thread.sleep(FINDING_DELAY);
}
catch (InterruptedException e)
{
}
}
}
}
});
thread.setDaemon(true);
thread.setName("Razer Hydra finder");
thread.start();
}
private static boolean loadLibrary()
{
return SixenseActivator.isLibraryLoaded();
}
private void startPolling()
{
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
Sixense.getAllNewestData(data);
try
{
processData();
}
catch (Exception e)
{
//don't allow exception in listeners to stop the thread; print it instead
e.printStackTrace();
}
try
{
Thread.sleep(POLLING_DELAY);
}
catch (InterruptedException e)
{
}
}
}
});
thread.setName("Razer Hydra poller");
thread.setDaemon(true);
thread.start();
}
private void processData()
{
listeners.updated(new HydraEvent(data[0], data[1]));
lastButton1 = processButtons(data[0].buttons, lastButton1, 1);
lastButton2 = processButtons(data[1].buttons, lastButton2, 2);
processSticks();
processTriggers();
}
private int processButtons(int value, int lastValue, int controller)
{
if (value != lastValue)
{
int mask = 1;
for (int i = 1; i < 16; i++)
{
if ((value & mask) != (lastValue & mask))
{
boolean down = (value & mask) != 0;
listeners.buttonChanged(new HydraButtonEvent(i, controller, down));
}
mask <<= 1;
}
}
return value;
}
private void processSticks()
{
if (lastStickEvent.stick1[0] != data[0].joystick_x || lastStickEvent.stick1[1] != data[0].joystick_y
|| lastStickEvent.stick2[0] != data[1].joystick_x || lastStickEvent.stick2[1] != data[1].joystick_y)
{
HydraStickEvent stickEvent = new HydraStickEvent();
stickEvent.stick1[0] = data[0].joystick_x;
stickEvent.stick1[1] = data[0].joystick_y;
stickEvent.stick2[0] = data[1].joystick_x;
stickEvent.stick2[1] = data[1].joystick_y;
stickEvent.delta1[0] = stickEvent.stick1[0] - lastStickEvent.stick1[0];
stickEvent.delta1[1] = stickEvent.stick1[1] - lastStickEvent.stick1[1];
stickEvent.delta2[0] = stickEvent.stick2[0] - lastStickEvent.stick2[0];
stickEvent.delta2[1] = stickEvent.stick2[1] - lastStickEvent.stick2[1];
listeners.stickChanged(stickEvent);
lastStickEvent = stickEvent;
}
}
private void processTriggers()
{
if (lastTriggerEvent.trigger1 != data[0].trigger || lastTriggerEvent.trigger2 != data[1].trigger)
{
HydraTriggerEvent triggerEvent = new HydraTriggerEvent();
triggerEvent.trigger1 = data[0].trigger;
triggerEvent.trigger2 = data[1].trigger;
triggerEvent.delta1 = triggerEvent.trigger1 - lastTriggerEvent.trigger1;
triggerEvent.delta2 = triggerEvent.trigger2 - lastTriggerEvent.trigger2;
listeners.triggerChanged(triggerEvent);
lastTriggerEvent = triggerEvent;
}
}
public void addListener(IHydraListener listener)
{
listeners.add(listener);
}
public void removeListener(IHydraListener listener)
{
listeners.remove(listener);
}
}