| /* |
| * 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.app.SettingsDialog; |
| import com.jme3.app.SettingsDialog.SelectionListener; |
| import com.jme3.asset.AssetManager; |
| import com.jme3.asset.AssetNotFoundException; |
| import com.jme3.asset.DesktopAssetManager; |
| import com.jme3.audio.AudioRenderer; |
| import com.jme3.system.JmeContext.Type; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import java.util.logging.Level; |
| import javax.swing.SwingUtilities; |
| |
| /** |
| * |
| * @author Kirill Vainer, normenhansen |
| */ |
| public class JmeDesktopSystem extends JmeSystemDelegate { |
| |
| @Override |
| public AssetManager newAssetManager(URL configFile) { |
| return new DesktopAssetManager(configFile); |
| } |
| |
| @Override |
| public AssetManager newAssetManager() { |
| return new DesktopAssetManager(null); |
| } |
| |
| @Override |
| public boolean showSettingsDialog(AppSettings sourceSettings, final boolean loadFromRegistry) { |
| if (SwingUtilities.isEventDispatchThread()) { |
| throw new IllegalStateException("Cannot run from EDT"); |
| } |
| |
| final AppSettings settings = new AppSettings(false); |
| settings.copyFrom(sourceSettings); |
| String iconPath = sourceSettings.getSettingsDialogImage(); |
| final URL iconUrl = JmeSystem.class.getResource(iconPath.startsWith("/") ? iconPath : "/" + iconPath); |
| if (iconUrl == null) { |
| throw new AssetNotFoundException(sourceSettings.getSettingsDialogImage()); |
| } |
| |
| final AtomicBoolean done = new AtomicBoolean(); |
| final AtomicInteger result = new AtomicInteger(); |
| final Object lock = new Object(); |
| |
| final SelectionListener selectionListener = new SelectionListener() { |
| |
| public void onSelection(int selection) { |
| synchronized (lock) { |
| done.set(true); |
| result.set(selection); |
| lock.notifyAll(); |
| } |
| } |
| }; |
| SwingUtilities.invokeLater(new Runnable() { |
| |
| public void run() { |
| synchronized (lock) { |
| SettingsDialog dialog = new SettingsDialog(settings, iconUrl, loadFromRegistry); |
| dialog.setSelectionListener(selectionListener); |
| dialog.showDialog(); |
| } |
| } |
| }); |
| |
| synchronized (lock) { |
| while (!done.get()) { |
| try { |
| lock.wait(); |
| } catch (InterruptedException ex) { |
| } |
| } |
| } |
| |
| sourceSettings.copyFrom(settings); |
| |
| return result.get() == SettingsDialog.APPROVE_SELECTION; |
| } |
| |
| private JmeContext newContextLwjgl(AppSettings settings, JmeContext.Type type) { |
| try { |
| Class<? extends JmeContext> ctxClazz = null; |
| switch (type) { |
| case Canvas: |
| ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.lwjgl.LwjglCanvas"); |
| break; |
| case Display: |
| ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.lwjgl.LwjglDisplay"); |
| break; |
| case OffscreenSurface: |
| ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.lwjgl.LwjglOffscreenBuffer"); |
| break; |
| default: |
| throw new IllegalArgumentException("Unsupported context type " + type); |
| } |
| |
| return ctxClazz.newInstance(); |
| } catch (InstantiationException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (IllegalAccessException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (ClassNotFoundException ex) { |
| logger.log(Level.SEVERE, "CRITICAL ERROR: Context class is missing!\n" |
| + "Make sure jme3_lwjgl-ogl is on the classpath.", ex); |
| } |
| |
| return null; |
| } |
| |
| private JmeContext newContextJogl(AppSettings settings, JmeContext.Type type) { |
| try { |
| Class<? extends JmeContext> ctxClazz = null; |
| switch (type) { |
| case Display: |
| ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.jogl.JoglDisplay"); |
| break; |
| case Canvas: |
| ctxClazz = (Class<? extends JmeContext>) Class.forName("com.jme3.system.jogl.JoglCanvas"); |
| break; |
| default: |
| throw new IllegalArgumentException("Unsupported context type " + type); |
| } |
| |
| return ctxClazz.newInstance(); |
| } catch (InstantiationException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (IllegalAccessException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (ClassNotFoundException ex) { |
| logger.log(Level.SEVERE, "CRITICAL ERROR: Context class is missing!\n" |
| + "Make sure jme3_jogl is on the classpath.", ex); |
| } |
| |
| return null; |
| } |
| |
| private JmeContext newContextCustom(AppSettings settings, JmeContext.Type type) { |
| try { |
| String className = settings.getRenderer().substring("CUSTOM".length()); |
| |
| Class<? extends JmeContext> ctxClazz = null; |
| ctxClazz = (Class<? extends JmeContext>) Class.forName(className); |
| return ctxClazz.newInstance(); |
| } catch (InstantiationException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (IllegalAccessException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (ClassNotFoundException ex) { |
| logger.log(Level.SEVERE, "CRITICAL ERROR: Context class is missing!", ex); |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public JmeContext newContext(AppSettings settings, Type contextType) { |
| initialize(settings); |
| JmeContext ctx; |
| if (settings.getRenderer() == null |
| || settings.getRenderer().equals("NULL") |
| || contextType == JmeContext.Type.Headless) { |
| ctx = new NullContext(); |
| ctx.setSettings(settings); |
| } else if (settings.getRenderer().startsWith("LWJGL")) { |
| ctx = newContextLwjgl(settings, contextType); |
| ctx.setSettings(settings); |
| } else if (settings.getRenderer().startsWith("JOGL")) { |
| ctx = newContextJogl(settings, contextType); |
| ctx.setSettings(settings); |
| } else if (settings.getRenderer().startsWith("CUSTOM")) { |
| ctx = newContextCustom(settings, contextType); |
| ctx.setSettings(settings); |
| } else { |
| throw new UnsupportedOperationException( |
| "Unrecognizable renderer specified: " |
| + settings.getRenderer()); |
| } |
| return ctx; |
| } |
| |
| @Override |
| public AudioRenderer newAudioRenderer(AppSettings settings) { |
| initialize(settings); |
| Class<? extends AudioRenderer> clazz = null; |
| try { |
| if (settings.getAudioRenderer().startsWith("LWJGL")) { |
| clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.lwjgl.LwjglAudioRenderer"); |
| } else if (settings.getAudioRenderer().startsWith("JOAL")) { |
| clazz = (Class<? extends AudioRenderer>) Class.forName("com.jme3.audio.joal.JoalAudioRenderer"); |
| } else { |
| throw new UnsupportedOperationException( |
| "Unrecognizable audio renderer specified: " |
| + settings.getAudioRenderer()); |
| } |
| |
| AudioRenderer ar = clazz.newInstance(); |
| return ar; |
| } catch (InstantiationException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (IllegalAccessException ex) { |
| logger.log(Level.SEVERE, "Failed to create context", ex); |
| } catch (ClassNotFoundException ex) { |
| logger.log(Level.SEVERE, "CRITICAL ERROR: Audio implementation class is missing!\n" |
| + "Make sure jme3_lwjgl-oal or jm3_joal is on the classpath.", ex); |
| } |
| return null; |
| } |
| |
| @Override |
| public void initialize(AppSettings settings) { |
| if (initialized) { |
| return; |
| } |
| |
| initialized = true; |
| try { |
| if (!lowPermissions) { |
| // can only modify logging settings |
| // if permissions are available |
| // JmeFormatter formatter = new JmeFormatter(); |
| // Handler fileHandler = new FileHandler("jme.log"); |
| // fileHandler.setFormatter(formatter); |
| // Logger.getLogger("").addHandler(fileHandler); |
| // Handler consoleHandler = new ConsoleHandler(); |
| // consoleHandler.setFormatter(formatter); |
| // Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]); |
| // Logger.getLogger("").addHandler(consoleHandler); |
| } |
| // } catch (IOException ex){ |
| // logger.log(Level.SEVERE, "I/O Error while creating log file", ex); |
| } catch (SecurityException ex) { |
| logger.log(Level.SEVERE, "Security error in creating log file", ex); |
| } |
| logger.log(Level.INFO, "Running on {0}", getFullName()); |
| |
| if (!lowPermissions) { |
| try { |
| Natives.extractNativeLibs(getPlatform(), settings); |
| } catch (IOException ex) { |
| logger.log(Level.SEVERE, "Error while copying native libraries", ex); |
| } |
| } |
| } |
| } |