Add a 3D enabled user preference
Add 3d Crash detection that disables 3d if the application crashes during one of several touchy phases of JOGL / Native / display driver initialization. Always make the 3D view button clickable, but there is an explanation and a button to turn 3d on if it has been disabled
This commit is contained in:
parent
2aa4a8d905
commit
4073246388
@ -1,3 +1,9 @@
|
||||
2012-09-27 Bill Kuker
|
||||
|
||||
* Added user preference to enable/disable 3D, and crash detection to disable 3D on a crash
|
||||
|
||||
* Moved JOGL GL initialization earlier in initialization.
|
||||
|
||||
2012-09-25 Doug Pedrick
|
||||
|
||||
* Added preference to open last edited design file upon startup.
|
||||
|
@ -52,6 +52,8 @@ RocketPanel.FigViewAct.2D = 2D View
|
||||
RocketPanel.FigViewAct.ttip.2D = 2D View
|
||||
RocketPanel.FigViewAct.3D = 3D View
|
||||
RocketPanel.FigViewAct.ttip.3D = 3D View
|
||||
RocketPanel.3DDisabledMessage = OpenRocket's 3D capabilities have been disabled by either the user or a crash.
|
||||
RocketPanel.3DDisabledMessageButton = Re-enable 3D at next application launch.
|
||||
RocketPanel.lbl.Motorcfg = Motor configuration:
|
||||
RocketPanel.lbl.infoMessage = <html>Click to select Shift+click to select other Double-click to edit Click+drag to move
|
||||
|
||||
@ -221,6 +223,7 @@ pref.dlg.but.add = Add
|
||||
pref.dlg.but.reset = Reset
|
||||
pref.dlg.but.checknow = Check now
|
||||
pref.dlg.but.openlast = Open last design file on startup
|
||||
pref.dlg.but.enable3d = Enable 3D
|
||||
pref.dlg.but.defaultmetric = Default metric
|
||||
pref.dlg.but.defaultimperial = Default imperial
|
||||
pref.dlg.title.Preferences = Preferences
|
||||
|
@ -298,7 +298,19 @@ public class PreferencesDialog extends JDialog {
|
||||
Application.getPreferences().setAutoOpenLastDesignOnStartup(autoOpenDesignFile.isSelected());
|
||||
}
|
||||
});
|
||||
panel.add(autoOpenDesignFile);
|
||||
panel.add(autoOpenDesignFile, "wrap");
|
||||
|
||||
|
||||
final JCheckBox enable3D = new JCheckBox(trans.get("pref.dlg.but.enable3d"));
|
||||
enable3D.setSelected(Application.getPreferences().is3dEnabled());
|
||||
enable3D.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
Application.getPreferences().set3dEnabled(enable3D.isSelected());
|
||||
}
|
||||
});
|
||||
panel.add(enable3D);
|
||||
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
125
core/src/net/sf/openrocket/gui/figure3d/OpenGLUtils.java
Normal file
125
core/src/net/sf/openrocket/gui/figure3d/OpenGLUtils.java
Normal file
@ -0,0 +1,125 @@
|
||||
package net.sf.openrocket.gui.figure3d;
|
||||
|
||||
import java.awt.SplashScreen;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import javax.media.opengl.GLProfile;
|
||||
|
||||
import net.sf.openrocket.arch.SystemInfo;
|
||||
import net.sf.openrocket.arch.SystemInfo.Platform;
|
||||
import net.sf.openrocket.gui.main.Splash;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
public class OpenGLUtils {
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
|
||||
/**
|
||||
* Keep the state of 3D consistent for the entire launch, so if user enables
|
||||
* 3d and opens a new window it stays disabled.
|
||||
*/
|
||||
private static Boolean enabledThisLaunch = null;
|
||||
|
||||
/**
|
||||
* set true in enterDangerZone, false in exitDangerZone allows the exit
|
||||
* function to return immediately if called extra times
|
||||
*/
|
||||
private static boolean inTheDangerZone = false;
|
||||
|
||||
/**
|
||||
* Call this method as early as possible.
|
||||
*/
|
||||
public static void earlyInitialize() {
|
||||
// If crash detection fails this will allow someone to disable
|
||||
// the 3d preference from the command line.
|
||||
if (System.getProperty("openrocket.3d.disable") != null) {
|
||||
Application.getPreferences().set3dEnabled(false);
|
||||
}
|
||||
|
||||
if (!is3dEnabled()) {
|
||||
log.debug("OpenGL is disabled");
|
||||
} else {
|
||||
log.debug("Initializing OpenGL");
|
||||
enterDangerZone();
|
||||
if (SystemInfo.getPlatform() == Platform.UNIX) {
|
||||
log.debug("Dismissing splash screen (Linux/Java/JOGL bug)");
|
||||
// Fixes a linux / X bug: Splash must be closed before GL Init
|
||||
SplashScreen splash = Splash.getSplashScreen();
|
||||
if (splash != null && splash.isVisible())
|
||||
splash.close();
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
// Intentionally Ignored
|
||||
}
|
||||
}
|
||||
log.debug("Calling GLProfile.initSingleton()");
|
||||
GLProfile.initSingleton();
|
||||
exitDangerZone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if 3d functions are enabled
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean is3dEnabled() {
|
||||
if (enabledThisLaunch == null)
|
||||
enabledThisLaunch = new Boolean(Application.getPreferences().is3dEnabled());
|
||||
return enabledThisLaunch.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal that we are about to do something that can cause a GL crash. If
|
||||
* exitDangerZone is not called after this the 3D user preference will be
|
||||
* disabled at the next startup.
|
||||
*/
|
||||
static void enterDangerZone() {
|
||||
log.verbose("Entering GL DangerZone");
|
||||
inTheDangerZone = true;
|
||||
Application.getPreferences().set3dEnabled(false);
|
||||
try {
|
||||
Preferences.userRoot().flush();
|
||||
} catch (BackingStoreException e) {
|
||||
log.warn("Unable to flush prefs in enterDangerZone()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal that some GL operation has succeeded. the UserPreference will be
|
||||
* left alone.
|
||||
*
|
||||
* Safe to call when not in the danger-zone. Safe to call quite often
|
||||
*/
|
||||
static void exitDangerZone() {
|
||||
if (!inTheDangerZone)
|
||||
return;
|
||||
inTheDangerZone = false;
|
||||
log.verbose("Exiting GL DangerZone");
|
||||
Application.getPreferences().set3dEnabled(true);
|
||||
try {
|
||||
Preferences.userRoot().flush();
|
||||
} catch (BackingStoreException e) {
|
||||
log.warn("Unable to flush prefs in exitDangerZone()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seriously never call this it will segfault the JVM.
|
||||
@Deprecated
|
||||
static void segfault(){
|
||||
try {
|
||||
log.error("Segfaulting!");
|
||||
Field f = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
f.setAccessible(true);
|
||||
Unsafe unsafe = (Unsafe)f.get(null);
|
||||
unsafe.putAddress(0, 0);
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to segfault", e);
|
||||
}
|
||||
|
||||
}
|
||||
**/
|
||||
}
|
@ -6,7 +6,10 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.SplashScreen;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.HierarchyEvent;
|
||||
import java.awt.event.HierarchyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -25,16 +28,18 @@ import javax.media.opengl.awt.GLCanvas;
|
||||
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
||||
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
||||
import javax.media.opengl.glu.GLU;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.figureelements.CGCaret;
|
||||
import net.sf.openrocket.gui.figureelements.CPCaret;
|
||||
import net.sf.openrocket.gui.figureelements.FigureElement;
|
||||
import net.sf.openrocket.gui.main.Splash;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.rocketcomponent.Configuration;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
@ -50,6 +55,7 @@ import com.jogamp.opengl.util.awt.Overlay;
|
||||
public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
static {
|
||||
//this allows the GL canvas and things like the motor selection
|
||||
@ -64,8 +70,6 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
private Configuration configuration;
|
||||
private GLCanvas canvas;
|
||||
|
||||
|
||||
|
||||
private Overlay extrasOverlay, caretOverlay;
|
||||
private BufferedImage cgCaretRaster, cpCaretRaster;
|
||||
private volatile boolean redrawExtras = true;
|
||||
@ -88,27 +92,49 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
//Only initizlize GL if 3d is enabled.
|
||||
if (is3dEnabled()) {
|
||||
//Fixes a linux / X bug: Splash must be closed before GL Init
|
||||
SplashScreen splash = Splash.getSplashScreen();
|
||||
if (splash != null && splash.isVisible())
|
||||
splash.close();
|
||||
|
||||
if ( OpenGLUtils.is3dEnabled() ){
|
||||
initGLCanvas();
|
||||
addHierarchyListener(new HierarchyListener(){
|
||||
@Override
|
||||
public void hierarchyChanged(HierarchyEvent e) {
|
||||
OpenGLUtils.enterDangerZone();
|
||||
RocketFigure3d.this.removeHierarchyListener(this);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setupDisabledUI();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if 3d view is enabled. This may be toggled by the user at
|
||||
* launch time.
|
||||
* @return
|
||||
* Draws a pretty primitive UI that explains that 3D is not enabled.
|
||||
*/
|
||||
public static boolean is3dEnabled() {
|
||||
return System.getProperty("openrocket.3d.disable") == null;
|
||||
private void setupDisabledUI(){
|
||||
canvas = null;
|
||||
final JPanel panel = new JPanel(new MigLayout("filly"));
|
||||
panel.add(new JLabel(trans.get("RocketPanel.3DDisabledMessage")));
|
||||
|
||||
if ( !Application.getPreferences().is3dEnabled() ){
|
||||
//this button lets them turn GL on without going to the preference menu.
|
||||
final JButton enable = new JButton(trans.get("RocketPanel.3DDisabledMessageButton"));
|
||||
enable.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
Application.getPreferences().set3dEnabled(true);
|
||||
panel.remove(enable);
|
||||
panel.revalidate();
|
||||
panel.repaint();
|
||||
}
|
||||
});
|
||||
panel.add(enable);
|
||||
}
|
||||
|
||||
this.add(panel);
|
||||
}
|
||||
|
||||
private void initGLCanvas() {
|
||||
log.debug("Initializing RocketFigure3D OpenGL Canvas");
|
||||
OpenGLUtils.enterDangerZone();
|
||||
try {
|
||||
log.debug("Setting up GL capabilities...");
|
||||
|
||||
@ -139,7 +165,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
log.verbose("GL - Setting up mouse listeners");
|
||||
setupMouseListeners();
|
||||
|
||||
log.verbose("GL - Rasterizine Carets"); //reticulating splines?
|
||||
log.verbose("GL - Rasterizing Carets"); //reticulating splines?
|
||||
rasterizeCarets();
|
||||
|
||||
} catch (Throwable t) {
|
||||
@ -147,6 +173,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
canvas = null;
|
||||
this.add(new JLabel("Unable to load 3d Libraries: "
|
||||
+ t.getMessage()));
|
||||
} finally {
|
||||
OpenGLUtils.exitDangerZone();
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,6 +313,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
|
||||
drawExtras(gl, glu);
|
||||
drawCarets(gl, glu);
|
||||
|
||||
OpenGLUtils.exitDangerZone();
|
||||
}
|
||||
|
||||
|
||||
@ -567,7 +597,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
||||
glu.gluProject(c.x, c.y, c.z, mvmatrix, 0, projmatrix, 0, viewport, 0,
|
||||
out, 0);
|
||||
|
||||
log.verbose("GL - peoject() complete");
|
||||
log.verbose("GL - project() complete");
|
||||
return new Coordinate(out[0], out[1], out[2]);
|
||||
|
||||
}
|
||||
|
@ -285,7 +285,6 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
||||
}
|
||||
});
|
||||
bg.add(toggle3d);
|
||||
toggle3d.setEnabled(RocketFigure3d.is3dEnabled());
|
||||
add(toggle3d, "gap rel");
|
||||
|
||||
// Zoom level selector
|
||||
|
@ -49,6 +49,7 @@ public abstract class Preferences {
|
||||
// Node names
|
||||
public static final String PREFERRED_THRUST_CURVE_MOTOR_NODE = "preferredThrustCurveMotors";
|
||||
private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN";
|
||||
private static final String THREE_D_ENABLED = "THREE_D_ENABLED";
|
||||
|
||||
/*
|
||||
* ******************************************************************************************
|
||||
@ -115,6 +116,22 @@ public abstract class Preferences {
|
||||
return this.getBoolean(AUTO_OPEN_LAST_DESIGN, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the 3d functionality
|
||||
* @param enabled
|
||||
*/
|
||||
public final void set3dEnabled(boolean enabled){
|
||||
this.putBoolean(THREE_D_ENABLED, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if 3d is enabled.
|
||||
*/
|
||||
public final boolean is3dEnabled(){
|
||||
return this.getBoolean(THREE_D_ENABLED, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OpenRocket unique ID.
|
||||
*
|
||||
|
@ -4,6 +4,7 @@ import java.io.PrintStream;
|
||||
import java.util.Locale;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.OpenGLUtils;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.l10n.DebugTranslator;
|
||||
import net.sf.openrocket.l10n.L10N;
|
||||
@ -51,6 +52,8 @@ public class Startup {
|
||||
|
||||
Application.setPreferences( new SwingPreferences() );
|
||||
|
||||
OpenGLUtils.earlyInitialize();
|
||||
|
||||
// Setup the translations
|
||||
initializeL10n();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user