NullContext.java 6.4 KB

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