• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
32 
33 package com.jme3.system;
34 
35 import com.jme3.input.JoyInput;
36 import com.jme3.input.KeyInput;
37 import com.jme3.input.MouseInput;
38 import com.jme3.input.TouchInput;
39 import com.jme3.input.dummy.DummyKeyInput;
40 import com.jme3.input.dummy.DummyMouseInput;
41 import com.jme3.renderer.Renderer;
42 import java.util.concurrent.atomic.AtomicBoolean;
43 import java.util.logging.Level;
44 import java.util.logging.Logger;
45 
46 public class NullContext implements JmeContext, Runnable {
47 
48     protected static final Logger logger = Logger.getLogger(NullContext.class.getName());
49 
50     protected AtomicBoolean created = new AtomicBoolean(false);
51     protected AtomicBoolean needClose = new AtomicBoolean(false);
52     protected final Object createdLock = new Object();
53 
54     protected int frameRate;
55     protected AppSettings settings = new AppSettings(true);
56     protected Timer timer;
57     protected SystemListener listener;
58     protected NullRenderer renderer;
59 
getType()60     public Type getType() {
61         return Type.Headless;
62     }
63 
setSystemListener(SystemListener listener)64     public void setSystemListener(SystemListener listener){
65         this.listener = listener;
66     }
67 
initInThread()68     protected void initInThread(){
69         logger.info("NullContext created.");
70         logger.log(Level.FINE, "Running on thread: {0}", Thread.currentThread().getName());
71 
72         Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
73             public void uncaughtException(Thread thread, Throwable thrown) {
74                 listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown);
75             }
76         });
77 
78         timer = new NanoTimer();
79         renderer = new NullRenderer();
80         synchronized (createdLock){
81             created.set(true);
82             createdLock.notifyAll();
83         }
84 
85         listener.initialize();
86     }
87 
deinitInThread()88     protected void deinitInThread(){
89         listener.destroy();
90         timer = null;
91         synchronized (createdLock){
92             created.set(false);
93             createdLock.notifyAll();
94         }
95     }
96 
97     private static long timeThen;
98     private static long timeLate;
99 
sync(int fps)100     public void sync(int fps) {
101         long timeNow;
102         long gapTo;
103         long savedTimeLate;
104 
105         gapTo = timer.getResolution() / fps + timeThen;
106         timeNow = timer.getTime();
107         savedTimeLate = timeLate;
108 
109         try {
110             while (gapTo > timeNow + savedTimeLate) {
111                 Thread.sleep(1);
112                 timeNow = timer.getTime();
113             }
114         } catch (InterruptedException e) {
115             Thread.currentThread().interrupt();
116         }
117 
118         if (gapTo < timeNow) {
119             timeLate = timeNow - gapTo;
120         } else {
121             timeLate = 0;
122         }
123 
124         timeThen = timeNow;
125     }
126 
run()127     public void run(){
128         initInThread();
129 
130         while (!needClose.get()){
131             listener.update();
132 
133             if (frameRate > 0)
134                 sync(frameRate);
135         }
136 
137         deinitInThread();
138 
139         logger.info("NullContext destroyed.");
140     }
141 
destroy(boolean waitFor)142     public void destroy(boolean waitFor){
143         needClose.set(true);
144         if (waitFor)
145             waitFor(false);
146     }
147 
create(boolean waitFor)148     public void create(boolean waitFor){
149         if (created.get()){
150             logger.warning("create() called when NullContext is already created!");
151             return;
152         }
153 
154         new Thread(this, "Headless Application Thread").start();
155         if (waitFor)
156             waitFor(true);
157     }
158 
restart()159     public void restart() {
160     }
161 
setAutoFlushFrames(boolean enabled)162     public void setAutoFlushFrames(boolean enabled){
163     }
164 
getMouseInput()165     public MouseInput getMouseInput() {
166         return new DummyMouseInput();
167     }
168 
getKeyInput()169     public KeyInput getKeyInput() {
170         return new DummyKeyInput();
171     }
172 
getJoyInput()173     public JoyInput getJoyInput() {
174         return null;
175     }
176 
getTouchInput()177     public TouchInput getTouchInput() {
178         return null;
179     }
180 
setTitle(String title)181     public void setTitle(String title) {
182     }
183 
create()184     public void create(){
185         create(false);
186     }
187 
destroy()188     public void destroy(){
189         destroy(false);
190     }
191 
waitFor(boolean createdVal)192     protected void waitFor(boolean createdVal){
193         synchronized (createdLock){
194             while (created.get() != createdVal){
195                 try {
196                     createdLock.wait();
197                 } catch (InterruptedException ex) {
198                 }
199             }
200         }
201     }
202 
isCreated()203     public boolean isCreated(){
204         return created.get();
205     }
206 
setSettings(AppSettings settings)207     public void setSettings(AppSettings settings) {
208         this.settings.copyFrom(settings);
209         frameRate = settings.getFrameRate();
210         if (frameRate <= 0)
211             frameRate = 60; // use default update rate.
212     }
213 
getSettings()214     public AppSettings getSettings(){
215         return settings;
216     }
217 
getRenderer()218     public Renderer getRenderer() {
219         return renderer;
220     }
221 
getTimer()222     public Timer getTimer() {
223         return timer;
224     }
225 
isRenderable()226     public boolean isRenderable() {
227         return true; // Doesn't really matter if true or false. Either way
228                      // RenderManager won't render anything.
229     }
230 }
231