2013-07-01 3 views
2

Я использую Java jinput библиотеку для чтения данных из джойстика, и у меня есть проблема перегрузка Controllers, я использую это, чтобы загрузить их:Java Jinput: контроллеры Пересканировать/перезарядки

public Controller[] findStickControllers() { 
    ControllerEnvironment ce = 
      ControllerEnvironment.getDefaultEnvironment(); 

    Controller[] cs = ce.getControllers(); 

    System.out.println(cs.length); //test 

    ArrayList<Controller> sel = new ArrayList<>(); 

    for (Controller c: cs) { 
     if(c.getType() == Type.STICK) { 
      sel.add(c); 
     } 
    } 

    return sel.toArray(new Controller[]{}); 
} 

Это работает отлично, но если я отключите мой контроллер, вызывая это, он снова найдет его, и наоборот (соединение его после первой проверки не обнаружит его вообще).

Я попытался положить спать до кулачного поиска, с этими результатами:

  1. Контроллеры Acctually сканируются, когда этот метод вызывается первый раз (не в начале программы)
  2. При вызове снова , это всегда возвращает те же самые контроллеры, которые были возвращены в первый раз.
  3. Первый вызов будет также написать предупреждение ниже
  4. Даже если контроллер подключен (и работает), а затем отключается (он все равно будет его найти, хотя) и соединившихся, он не будет работать

Предупреждение от точки 3 : (не формат хорошо в списке)

WARNING: Found unknown Windows version: Windows 8 
Attempting to use default windows plug-in. 
Loading: net.java.games.input.DirectAndRawInputEnvironmentPlugin 

Я использую Win 8, и была такая же проблема на Win 7. Я также попытался это с мышью, те же результаты.

Как я могу нормально перезагрузить контроллеры для 2-го, 3-го и так далее?

+1

Существует PR с исправлением hotplug, ожидающим объединения здесь. https://github.com/jinput/jinput/pull/11 –

ответ

6

я столкнулся с той же проблемой. Причина в том, что фактическое сканирование оборудования происходит только один раз для каждого объекта DefaultControllerEnvironment. Поскольку единственный доступный экземпляр является одиночным, он никогда не выполняет другого сканирования.

Простым способом принудительного сканирования оборудования является создание нового объекта, но ни класс, ни конструктор не являются общедоступными. Однако вы можете обойти это ограничение, вызвав конструктор через отражение.

Пересканировать

private static ControllerEnvironment createDefaultEnvironment() throws ReflectiveOperationException { 

    // Find constructor (class is package private, so we can't access it directly) 
    Constructor<ControllerEnvironment> constructor = (Constructor<ControllerEnvironment>) 
     Class.forName("net.java.games.input.DefaultControllerEnvironment").getDeclaredConstructors()[0]; 

    // Constructor is package private, so we have to deactivate access control checks 
    constructor.setAccessible(true); 

    // Create object with default constructor 
    return constructor.newInstance(); 
} 

Использования

// Be aware that creating a new environment is fairly expensive 
Controller[] controllers = createDefaultEnvironment().getControllers(); 

удалить Windows 8 Предупреждения

/** 
* Fix windows 8 warnings by defining a working plugin 
*/ 
static { 

    AccessController.doPrivileged(new PrivilegedAction<Object>() { 
     public Object run() { 
      String os = System.getProperty("os.name", "").trim(); 
      if (os.startsWith("Windows 8")) { // 8, 8.1 etc. 

       // disable default plugin lookup 
       System.setProperty("jinput.useDefaultPlugin", "false"); 

       // set to same as windows 7 (tested for windows 8 and 8.1) 
       System.setProperty("net.java.games.input.plugins", "net.java.games.input.DirectAndRawInputEnvironmentPlugin"); 

      } 
      return null; 
     } 
    }); 

} 
+1

Я добавил этот метод (createDefaultEnvironment), где основной метод, но я не могу заставить его работать. Если вы можете добавить более подробную информацию, я был бы очень благодарен. – Aelgawad

+1

Я добавил пример. По существу вам нужно заменить вызовы ControllerEnvironment.getDefaultEnvironment() с createDefaultEnvironment() –

+0

Это сработало! Огромное спасибо. – Aelgawad

1

Предупреждение связано с тем, что в последний раз, когда я обновлял этот код Windows 7, даже не был выпущен IIRC, я обновлю его.

Резервирование контроллера - это функция, которая запрашивалась несколько раз, но никто не считает ее достаточно важной, чтобы тратить ее на любое время. Если вы отправите патч, я взгляну и посмотрю, как это сделать. Пока кто-то не считает это достаточно важным, чтобы тратить время на его запись, это просто недостающая функция.

+0

* никто не считает это достаточно важным, чтобы тратить время на его реализацию * Я совершенно удивлен. Однако похоже, что это правда. Я уже избегал этой проблемы, открывая новый 'Process' каждый раз, когда я хочу пересканировать контроллеры, но это действительно отстой. – kajacx

1

У меня была такая же проблема и раньше. Я добавляю функцию повторного сканирования (только для Windows-back-end) и публикую патч на Java-игровом форуме, но ни один из них не заинтересован в его интеграции.

Так что, если вам это нужно, применить мой патч здесь: http://www.java-gaming.org/topics/rescan-controllers/24782/msg/224604/view.html#msg224604

+0

Whoa, я использовал другую работу, но спасибо в любом случае! – kajacx

0

Если вы используете принятый ответ, вы можете рассмотреть убить поток, который был порожден предыдущей среде перед установкой новой, потому что она не будет очищена в противном случае. Вы можете сделать это, позвонив примерно так:

final Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); 
for (final Thread thread : threadSet) { 
    final String name = thread.getClass().getName(); 
    if (name.equals("net.java.games.input.RawInputEventQueue$QueueThread")) { 
    thread.interrupt(); 
    try { 
     thread.join(); 
    } catch (final InterruptedException e) { 
     thread.interrupt(); 
    } 
    } 
} 
Смежные вопросы