Home | History | Annotate | Download | only in system
      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 
     34 import com.jme3.app.SettingsDialog;
     35 import com.jme3.app.SettingsDialog.SelectionListener;
     36 import com.jme3.asset.AssetManager;
     37 import com.jme3.asset.AssetNotFoundException;
     38 import com.jme3.asset.DesktopAssetManager;
     39 import com.jme3.audio.AudioRenderer;
     40 import com.jme3.system.JmeContext.Type;
     41 import java.io.IOException;
     42 import java.net.URL;
     43 import java.util.concurrent.atomic.AtomicBoolean;
     44 import java.util.concurrent.atomic.AtomicInteger;
     45 import java.util.logging.Level;
     46 import javax.swing.SwingUtilities;
     47 
     48 /**
     49  *
     50  * @author Kirill Vainer, normenhansen
     51  */
     52 public class JmeDesktopSystem extends JmeSystemDelegate {
     53 
     54     @Override
     55     public AssetManager newAssetManager(URL configFile) {
     56         return new DesktopAssetManager(configFile);
     57     }
     58 
     59     @Override
     60     public AssetManager newAssetManager() {
     61         return new DesktopAssetManager(null);
     62     }
     63 
     64     @Override
     65     public boolean showSettingsDialog(AppSettings sourceSettings, final boolean loadFromRegistry) {
     66         if (SwingUtilities.isEventDispatchThread()) {
     67             throw new IllegalStateException("Cannot run from EDT");
     68         }
     69 
     70         final AppSettings settings = new AppSettings(false);
     71         settings.copyFrom(sourceSettings);
     72         String iconPath = sourceSettings.getSettingsDialogImage();
     73         final URL iconUrl = JmeSystem.class.getResource(iconPath.startsWith("/") ? iconPath : "/" + iconPath);
     74         if (iconUrl == null) {
     75             throw new AssetNotFoundException(sourceSettings.getSettingsDialogImage());
     76         }
     77 
     78         final AtomicBoolean done = new AtomicBoolean();
     79         final AtomicInteger result = new AtomicInteger();
     80         final Object lock = new Object();
     81 
     82         final SelectionListener selectionListener = new SelectionListener() {
     83 
     84             public void onSelection(int selection) {
     85                 synchronized (lock) {
     86                     done.set(true);
     87                     result.set(selection);
     88                     lock.notifyAll();
     89                 }
     90             }
     91         };
     92         SwingUtilities.invokeLater(new Runnable() {
     93 
     94             public void run() {
     95                 synchronized (lock) {
     96                     SettingsDialog dialog = new SettingsDialog(settings, iconUrl, loadFromRegistry);
     97                     dialog.setSelectionListener(selectionListener);
     98                     dialog.showDialog();
     99                 }
    100             }
    101         });
    102 
    103         synchronized (lock) {
    104             while (!done.get()) {
    105                 try {
    106                     lock.wait();
    107                 } catch (InterruptedException ex) {
    108                 }
    109             }
    110         }
    111 
    112         sourceSettings.copyFrom(settings);
    113 
    114         return result.get() == SettingsDialog.APPROVE_SELECTION;
    115     }
    116 
    117     private JmeContext newContextLwjgl(AppSettings settings, JmeContext.Type type) {
    118         try {
    119             Class<? extends JmeContext> ctxClazz = null;
    120             switch (type) {
    121                 case Canvas:
    122                     ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.lwjgl.LwjglCanvas");
    123                     break;
    124                 case Display:
    125                     ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.lwjgl.LwjglDisplay");
    126                     break;
    127                 case OffscreenSurface:
    128                     ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.lwjgl.LwjglOffscreenBuffer");
    129                     break;
    130                 default:
    131                     throw new IllegalArgumentException("Unsupported context type " + type);
    132             }
    133 
    134             return ctxClazz.newInstance();
    135         } catch (InstantiationException ex) {
    136             logger.log(Level.SEVERE, "Failed to create context", ex);
    137         } catch (IllegalAccessException ex) {
    138             logger.log(Level.SEVERE, "Failed to create context", ex);
    139         } catch (ClassNotFoundException ex) {
    140             logger.log(Level.SEVERE, "CRITICAL ERROR: Context class is missing!\n"
    141                     + "Make sure jme3_lwjgl-ogl is on the classpath.", ex);
    142         }
    143 
    144         return null;
    145     }
    146 
    147     private JmeContext newContextJogl(AppSettings settings, JmeContext.Type type) {
    148         try {
    149             Class<? extends JmeContext> ctxClazz = null;
    150             switch (type) {
    151                 case Display:
    152                     ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.jogl.JoglDisplay");
    153                     break;
    154                 case Canvas:
    155                     ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.jogl.JoglCanvas");
    156                     break;
    157                 default:
    158                     throw new IllegalArgumentException("Unsupported context type " + type);
    159             }
    160 
    161             return ctxClazz.newInstance();
    162         } catch (InstantiationException ex) {
    163             logger.log(Level.SEVERE, "Failed to create context", ex);
    164         } catch (IllegalAccessException ex) {
    165             logger.log(Level.SEVERE, "Failed to create context", ex);
    166         } catch (ClassNotFoundException ex) {
    167             logger.log(Level.SEVERE, "CRITICAL ERROR: Context class is missing!\n"
    168                     + "Make sure jme3_jogl is on the classpath.", ex);
    169         }
    170 
    171         return null;
    172     }
    173 
    174     private JmeContext newContextCustom(AppSettings settings, JmeContext.Type type) {
    175         try {
    176             String className = settings.getRenderer().substring("CUSTOM".length());
    177 
    178             Class<? extends JmeContext> ctxClazz = null;
    179             ctxClazz = (Class<? extends JmeContext>) Class.forName(className);
    180             return ctxClazz.newInstance();
    181         } catch (InstantiationException ex) {
    182             logger.log(Level.SEVERE, "Failed to create context", ex);
    183         } catch (IllegalAccessException ex) {
    184             logger.log(Level.SEVERE, "Failed to create context", ex);
    185         } catch (ClassNotFoundException ex) {
    186             logger.log(Level.SEVERE, "CRITICAL ERROR: Context class is missing!", ex);
    187         }
    188 
    189         return null;
    190     }
    191 
    192     @Override
    193     public JmeContext newContext(AppSettings settings, Type contextType) {
    194         initialize(settings);
    195         JmeContext ctx;
    196         if (settings.getRenderer() == null
    197                 || settings.getRenderer().equals("NULL")
    198                 || contextType == JmeContext.Type.Headless) {
    199             ctx = new NullContext();
    200             ctx.setSettings(settings);
    201         } else if (settings.getRenderer().startsWith("LWJGL")) {
    202             ctx = newContextLwjgl(settings, contextType);
    203             ctx.setSettings(settings);
    204         } else if (settings.getRenderer().startsWith("JOGL")) {
    205             ctx = newContextJogl(settings, contextType);
    206             ctx.setSettings(settings);
    207         } else if (settings.getRenderer().startsWith("CUSTOM")) {
    208             ctx = newContextCustom(settings, contextType);
    209             ctx.setSettings(settings);
    210         } else {
    211             throw new UnsupportedOperationException(
    212                     "Unrecognizable renderer specified: "
    213                     + settings.getRenderer());
    214         }
    215         return ctx;
    216     }
    217 
    218     @Override
    219     public AudioRenderer newAudioRenderer(AppSettings settings) {
    220         initialize(settings);
    221         Class<? extends AudioRenderer> clazz = null;
    222         try {
    223             if (settings.getAudioRenderer().startsWith("LWJGL")) {
    224                 clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.lwjgl.LwjglAudioRenderer");
    225             } else if (settings.getAudioRenderer().startsWith("JOAL")) {
    226                 clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.joal.JoalAudioRenderer");
    227             } else {
    228                 throw new UnsupportedOperationException(
    229                         "Unrecognizable audio renderer specified: "
    230                         + settings.getAudioRenderer());
    231             }
    232 
    233             AudioRenderer ar = clazz.newInstance();
    234             return ar;
    235         } catch (InstantiationException ex) {
    236             logger.log(Level.SEVERE, "Failed to create context", ex);
    237         } catch (IllegalAccessException ex) {
    238             logger.log(Level.SEVERE, "Failed to create context", ex);
    239         } catch (ClassNotFoundException ex) {
    240             logger.log(Level.SEVERE, "CRITICAL ERROR: Audio implementation class is missing!\n"
    241                     + "Make sure jme3_lwjgl-oal or jm3_joal is on the classpath.", ex);
    242         }
    243         return null;
    244     }
    245 
    246     @Override
    247     public void initialize(AppSettings settings) {
    248         if (initialized) {
    249             return;
    250         }
    251 
    252         initialized = true;
    253         try {
    254             if (!lowPermissions) {
    255                 // can only modify logging settings
    256                 // if permissions are available
    257 //                JmeFormatter formatter = new JmeFormatter();
    258 //                Handler fileHandler = new FileHandler("jme.log");
    259 //                fileHandler.setFormatter(formatter);
    260 //                Logger.getLogger("").addHandler(fileHandler);
    261 //                Handler consoleHandler = new ConsoleHandler();
    262 //                consoleHandler.setFormatter(formatter);
    263 //                Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]);
    264 //                Logger.getLogger("").addHandler(consoleHandler);
    265             }
    266 //        } catch (IOException ex){
    267 //            logger.log(Level.SEVERE, "I/O Error while creating log file", ex);
    268         } catch (SecurityException ex) {
    269             logger.log(Level.SEVERE, "Security error in creating log file", ex);
    270         }
    271         logger.log(Level.INFO, "Running on {0}", getFullName());
    272 
    273         if (!lowPermissions) {
    274             try {
    275                 Natives.extractNativeLibs(getPlatform(), settings);
    276             } catch (IOException ex) {
    277                 logger.log(Level.SEVERE, "Error while copying native libraries", ex);
    278             }
    279         }
    280     }
    281 }
    282