1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32package com.jme3.niftygui;
33
34import com.jme3.input.InputManager;
35import com.jme3.input.KeyInput;
36import com.jme3.input.RawInputListener;
37import com.jme3.input.SoftTextDialogInput;
38import com.jme3.input.controls.SoftTextDialogInputListener;
39import com.jme3.input.event.*;
40import com.jme3.system.JmeSystem;
41import de.lessvoid.nifty.Nifty;
42import de.lessvoid.nifty.NiftyInputConsumer;
43import de.lessvoid.nifty.controls.TextField;
44import de.lessvoid.nifty.controls.nullobjects.TextFieldNull;
45import de.lessvoid.nifty.elements.Element;
46import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;
47import de.lessvoid.nifty.input.keyboard.KeyboardInputEvent;
48import de.lessvoid.nifty.spi.input.InputSystem;
49import java.util.ArrayList;
50import java.util.logging.Level;
51import java.util.logging.Logger;
52
53public class InputSystemJme implements InputSystem, RawInputListener {
54
55    private final ArrayList<InputEvent> inputQueue = new ArrayList<InputEvent>();
56    private InputManager inputManager;
57    private boolean isDragging = false, niftyOwnsDragging = false;
58    private boolean pressed = false;
59    private int buttonIndex;
60    private int x, y;
61    private int height;
62    private boolean shiftDown = false;
63    private boolean ctrlDown = false;
64    private Nifty nifty;
65
66    public InputSystemJme(InputManager inputManager) {
67        this.inputManager = inputManager;
68    }
69
70    public void setResourceLoader(NiftyResourceLoader niftyResourceLoader) {
71    }
72
73    public void setNifty(Nifty nifty) {
74        this.nifty = nifty;
75    }
76
77    /**
78     * @param height The height of the viewport. Used to convert
79     * buttom-left origin to upper-left origin.
80     */
81    public void setHeight(int height) {
82        this.height = height;
83    }
84
85    public void setMousePosition(int x, int y) {
86    }
87
88    public void beginInput() {
89    }
90
91    public void endInput() {
92        boolean result = nifty.update();
93    }
94
95    private void onTouchEventQueued(TouchEvent evt, NiftyInputConsumer nic) {
96        boolean consumed = false;
97
98        x = (int) evt.getX();
99        y = (int) (height - evt.getY());
100
101        if (!inputManager.getSimulateMouse()) {
102            switch (evt.getType()) {
103                case DOWN:
104                    consumed = nic.processMouseEvent(x, y, 0, 0, true);
105                    isDragging = true;
106                    niftyOwnsDragging = consumed;
107                    if (consumed) {
108                        evt.setConsumed();
109                    }
110
111                    break;
112
113                case UP:
114                    if (niftyOwnsDragging) {
115                        consumed = nic.processMouseEvent(x, y, 0, 0, false);
116                        if (consumed) {
117                            evt.setConsumed();
118                        }
119                    }
120
121                    isDragging = false;
122                    niftyOwnsDragging = false;
123
124                    if (consumed) {
125                        processSoftKeyboard();
126                    }
127
128                    break;
129            }
130        }
131    }
132
133    private void onMouseMotionEventQueued(MouseMotionEvent evt, NiftyInputConsumer nic) {
134        x = evt.getX();
135        y = height - evt.getY();
136        nic.processMouseEvent(x, y, evt.getDeltaWheel(), buttonIndex, pressed);
137//        if (nic.processMouseEvent(niftyEvt) /*|| nifty.getCurrentScreen().isMouseOverElement()*/){
138        // Do not consume motion events
139        //evt.setConsumed();
140//        }
141    }
142
143    private void onMouseButtonEventQueued(MouseButtonEvent evt, NiftyInputConsumer nic) {
144        boolean wasPressed = pressed;
145        boolean forwardToNifty = true;
146
147        buttonIndex = evt.getButtonIndex();
148        pressed = evt.isPressed();
149
150        // Mouse button raised. End dragging
151        if (wasPressed && !pressed) {
152            if (!niftyOwnsDragging) {
153                forwardToNifty = false;
154            }
155            isDragging = false;
156            niftyOwnsDragging = false;
157        }
158
159        boolean consumed = false;
160        if (forwardToNifty) {
161            consumed = nic.processMouseEvent(x, y, 0, buttonIndex, pressed);
162            if (consumed) {
163                evt.setConsumed();
164            }
165        }
166
167        // Mouse button pressed. Begin dragging
168        if (!wasPressed && pressed) {
169            isDragging = true;
170            niftyOwnsDragging = consumed;
171        }
172
173        if (consumed && pressed) {
174            processSoftKeyboard();
175        }
176
177    }
178
179    private void onKeyEventQueued(KeyInputEvent evt, NiftyInputConsumer nic) {
180        int code = evt.getKeyCode();
181
182        if (code == KeyInput.KEY_LSHIFT || code == KeyInput.KEY_RSHIFT) {
183            shiftDown = evt.isPressed();
184        } else if (code == KeyInput.KEY_LCONTROL || code == KeyInput.KEY_RCONTROL) {
185            ctrlDown = evt.isPressed();
186        }
187
188        KeyboardInputEvent keyEvt = new KeyboardInputEvent(code,
189                evt.getKeyChar(),
190                evt.isPressed(),
191                shiftDown,
192                ctrlDown);
193
194        if (nic.processKeyboardEvent(keyEvt)) {
195            evt.setConsumed();
196        }
197    }
198
199    public void onMouseMotionEvent(MouseMotionEvent evt) {
200        // Only forward the event if there's actual motion involved.
201        if (inputManager.isCursorVisible() && (evt.getDX() != 0
202                || evt.getDY() != 0
203                || evt.getDeltaWheel() != 0)) {
204            inputQueue.add(evt);
205        }
206    }
207
208    public void onMouseButtonEvent(MouseButtonEvent evt) {
209        if (inputManager.isCursorVisible() && evt.getButtonIndex() >= 0 && evt.getButtonIndex() <= 2) {
210            inputQueue.add(evt);
211        }
212    }
213
214    public void onJoyAxisEvent(JoyAxisEvent evt) {
215    }
216
217    public void onJoyButtonEvent(JoyButtonEvent evt) {
218    }
219
220    public void onKeyEvent(KeyInputEvent evt) {
221        inputQueue.add(evt);
222    }
223
224    public void onTouchEvent(TouchEvent evt) {
225        inputQueue.add(evt);
226    }
227
228    public void forwardEvents(NiftyInputConsumer nic) {
229        int queueSize = inputQueue.size();
230
231        for (int i = 0; i < queueSize; i++) {
232            InputEvent evt = inputQueue.get(i);
233            if (evt instanceof MouseMotionEvent) {
234                onMouseMotionEventQueued((MouseMotionEvent) evt, nic);
235            } else if (evt instanceof MouseButtonEvent) {
236                onMouseButtonEventQueued((MouseButtonEvent) evt, nic);
237            } else if (evt instanceof KeyInputEvent) {
238                onKeyEventQueued((KeyInputEvent) evt, nic);
239            } else if (evt instanceof TouchEvent) {
240                onTouchEventQueued((TouchEvent) evt, nic);
241            }
242        }
243
244        inputQueue.clear();
245    }
246
247    private void processSoftKeyboard() {
248        SoftTextDialogInput softTextDialogInput = JmeSystem.getSoftTextDialogInput();
249        if (softTextDialogInput != null) {
250
251            Element element = nifty.getCurrentScreen().getFocusHandler().getKeyboardFocusElement();
252            if (element != null) {
253                final TextField textField = element.getNiftyControl(TextField.class);
254                if (textField != null && !(textField instanceof TextFieldNull)) {
255                    Logger.getLogger(InputSystemJme.class.getName()).log(Level.INFO, "Current TextField: {0}", textField.getId());
256                    String initialValue = textField.getText();
257                    if (initialValue == null) {
258                        initialValue = "";
259                    }
260
261                    softTextDialogInput.requestDialog(SoftTextDialogInput.TEXT_ENTRY_DIALOG, "Enter Text", initialValue, new SoftTextDialogInputListener() {
262
263                        public void onSoftText(int action, String text) {
264                            if (action == SoftTextDialogInputListener.COMPLETE) {
265                                textField.setText(text);
266                            }
267                        }
268                    });
269                }
270            }
271        }
272
273    }
274}
275