diff options
Diffstat (limited to 'engine/src/core/com/jme3/system/NullContext.java')
-rw-r--r-- | engine/src/core/com/jme3/system/NullContext.java | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/engine/src/core/com/jme3/system/NullContext.java b/engine/src/core/com/jme3/system/NullContext.java new file mode 100644 index 0000000..75fdf2b --- /dev/null +++ b/engine/src/core/com/jme3/system/NullContext.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2009-2010 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.system; + +import com.jme3.input.JoyInput; +import com.jme3.input.KeyInput; +import com.jme3.input.MouseInput; +import com.jme3.input.TouchInput; +import com.jme3.input.dummy.DummyKeyInput; +import com.jme3.input.dummy.DummyMouseInput; +import com.jme3.renderer.Renderer; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class NullContext implements JmeContext, Runnable { + + protected static final Logger logger = Logger.getLogger(NullContext.class.getName()); + + protected AtomicBoolean created = new AtomicBoolean(false); + protected AtomicBoolean needClose = new AtomicBoolean(false); + protected final Object createdLock = new Object(); + + protected int frameRate; + protected AppSettings settings = new AppSettings(true); + protected Timer timer; + protected SystemListener listener; + protected NullRenderer renderer; + + public Type getType() { + return Type.Headless; + } + + public void setSystemListener(SystemListener listener){ + this.listener = listener; + } + + protected void initInThread(){ + logger.info("NullContext created."); + logger.log(Level.FINE, "Running on thread: {0}", Thread.currentThread().getName()); + + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread thread, Throwable thrown) { + listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown); + } + }); + + timer = new NanoTimer(); + renderer = new NullRenderer(); + synchronized (createdLock){ + created.set(true); + createdLock.notifyAll(); + } + + listener.initialize(); + } + + protected void deinitInThread(){ + listener.destroy(); + timer = null; + synchronized (createdLock){ + created.set(false); + createdLock.notifyAll(); + } + } + + private static long timeThen; + private static long timeLate; + + public void sync(int fps) { + long timeNow; + long gapTo; + long savedTimeLate; + + gapTo = timer.getResolution() / fps + timeThen; + timeNow = timer.getTime(); + savedTimeLate = timeLate; + + try { + while (gapTo > timeNow + savedTimeLate) { + Thread.sleep(1); + timeNow = timer.getTime(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + if (gapTo < timeNow) { + timeLate = timeNow - gapTo; + } else { + timeLate = 0; + } + + timeThen = timeNow; + } + + public void run(){ + initInThread(); + + while (!needClose.get()){ + listener.update(); + + if (frameRate > 0) + sync(frameRate); + } + + deinitInThread(); + + logger.info("NullContext destroyed."); + } + + public void destroy(boolean waitFor){ + needClose.set(true); + if (waitFor) + waitFor(false); + } + + public void create(boolean waitFor){ + if (created.get()){ + logger.warning("create() called when NullContext is already created!"); + return; + } + + new Thread(this, "Headless Application Thread").start(); + if (waitFor) + waitFor(true); + } + + public void restart() { + } + + public void setAutoFlushFrames(boolean enabled){ + } + + public MouseInput getMouseInput() { + return new DummyMouseInput(); + } + + public KeyInput getKeyInput() { + return new DummyKeyInput(); + } + + public JoyInput getJoyInput() { + return null; + } + + public TouchInput getTouchInput() { + return null; + } + + public void setTitle(String title) { + } + + public void create(){ + create(false); + } + + public void destroy(){ + destroy(false); + } + + protected void waitFor(boolean createdVal){ + synchronized (createdLock){ + while (created.get() != createdVal){ + try { + createdLock.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public boolean isCreated(){ + return created.get(); + } + + public void setSettings(AppSettings settings) { + this.settings.copyFrom(settings); + frameRate = settings.getFrameRate(); + if (frameRate <= 0) + frameRate = 60; // use default update rate. + } + + public AppSettings getSettings(){ + return settings; + } + + public Renderer getRenderer() { + return renderer; + } + + public Timer getTimer() { + return timer; + } + + public boolean isRenderable() { + return true; // Doesn't really matter if true or false. Either way + // RenderManager won't render anything. + } +} |