0%

Jinput源码解析

Jinput

Java library for accessing input devices

The JInput Project hosts an implementation of an API for game controller discovery and polled input. It is part of a suite of open-source technologies initiated by the Game Technology Group at Sun Microsystems with intention of making the development of high performance games in Java a reality.

The API itself is pure Java and presents a platform-neutral completely portable model of controller discovery and polling. It can handle arbitrary controllers and returns both human and machine understandable descriptions of the inputs available.

The implementation hosted here also includes plug-ins to allow the API to adapt to various specific platforms. These plug-ins often contain a native code portion to interface to the host system.

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* 控制器-父类
*/
public abstract class AbstractController implements Controller {
public synchronized boolean poll() {
//所有组件(按键)
Component[] components = getComponents();
try {
pollDevice();
for (int i = 0; i < components.length; i++) {
AbstractComponent component = (AbstractComponent)components[i];
//重置组件状态
if (component.isRelative()) {
component.setPollData(0);
} else {
// Let the component poll itself lazily
component.resetHasPolled();
}
}
//刷新组件状态
while (getNextDeviceEvent(event)) {//有下一个事件
AbstractComponent component = (AbstractComponent)event.getComponent();
float value = event.getValue();
if (component.isRelative()) {
if (value == 0)
continue;
component.setPollData(component.getPollData() + value);
} else {
if (value == component.getEventValue())
continue;
component.setEventValue(value);
}
if (!event_queue.isFull())
event_queue.add(event);
}
return true;
} catch (IOException e) {
ControllerEnvironment.log("Failed to poll device: " + e.getMessage());
return false;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* DI控制器(手柄)
*/
final class DIAbstractController extends AbstractController {
private final IDirectInputDevice device;
/**
* 获取设备数据
*/
public final void pollDevice() throws IOException {
device.pollAll();
}

protected final boolean getNextDeviceEvent(Event event) throws IOException {
return DIControllers.getNextDeviceEvent(event, device);
}
}

final class DIControllers {
private final static DIDeviceObjectData di_event = new DIDeviceObjectData();
/**
* 获取下一个设备事件,事件相关信息会被设置到event对象中
*/
public final static synchronized boolean getNextDeviceEvent(Event event, IDirectInputDevice device) throws IOException {
if (!device.getNextEvent(di_event))
return false;
DIDeviceObject object = device.mapEvent(di_event);
DIComponent component = device.mapObject(object);
if (component == null)
return false;
int event_value;
if (object.isRelative()) {
event_value = object.getRelativeEventValue(di_event.getData());
} else {
event_value = di_event.getData();
}
event.set(component, component.getDeviceObject().convertValue(event_value), di_event.getNanos());
return true;
}

public final static float poll(Component component, DIDeviceObject object) throws IOException {
int poll_data = object.getDevice().getPollData(object);
float result;
if (object.isRelative()) {
result = object.getRelativePollValue(poll_data);
} else {
result = poll_data;
}
return object.convertValue(result);
}
}

InputDevice

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
final class IDirectInputDevice {
/**
* 查询键盘数据,并将查询到的数据(DIDeviceObjectData)放在队列queue中
*/
public final synchronized void pollAll() throws IOException {
checkReleased();
poll();
getDeviceState(device_state);
queue.compact();
getDeviceData(queue);
queue.flip();
}

private final boolean getDeviceData(DataQueue<DIDeviceObjectData> queue) throws IOException {
int res = nGetDeviceData(address, 0, queue, queue.getElements(), queue.position(), queue.remaining());
if (res != DI_OK && res != DI_BUFFEROVERFLOW) {
if (res == DIERR_NOTACQUIRED) {
acquire();
return false;
}
throw new IOException("Failed to get device data (" + Integer.toHexString(res) + ")");
}
return true;
}

private final static native int nGetDeviceData(long address, int flags, DataQueue<DIDeviceObjectData> queue, Object[] queue_elements, int position, int remaining);

public synchronized final boolean getNextEvent(DIDeviceObjectData data) {
DIDeviceObjectData next_event = queue.get();
if (next_event == null)
return false;
data.set(next_event);
return true;
}
}

final class DataQueue<T> {
private final T[] elements;
private int position;
private int limit;
public final void compact() {
int index = 0;
//从position开始与index交换元素,直到position=limit
while (hasRemaining()) {
swap(position, index);
position++;
index++;
}
//将position修改为最后一个index
position = index;
limit = elements.length;
}
//翻转
public final void flip() {
limit = position;
position = 0;
}

public final boolean hasRemaining() {
return remaining() > 0;
}

public final int remaining() {
return limit - position;
}

public final void clear() {
position = 0;
limit = elements.length;
}
}

final class DIDeviceObjectData {
private int format_offset;
private int data;
private int millis;
private int sequence;

public final void set(int format_offset, int data, int millis, int sequence) {
this.format_offset = format_offset;
this.data = data;
this.millis = millis;
this.sequence = sequence;
}

public final void set(DIDeviceObjectData other) {
set(other.format_offset, other.data, other.millis, other.sequence);
}

public final int getData() {
return data;
}

public final int getFormatOffset() {
return format_offset;
}

public final long getNanos() {
return millis*1000000L;
}
}

总结

通过Controller查询输入数据,最终调用Device查询底层输入数据,保存到队列queue中,再从队列queue中取出作为event传递到Controller中的component,并更新其属性pollData

您的支持是对我最大的动力 (●'◡'●)