Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Commit

Permalink
Fix mouse selection with SWT DPI autoscaling.
Browse files Browse the repository at this point in the history
Separate drawing and picking rendering.
Adapt package level logger.
  • Loading branch information
leeca committed Jan 23, 2017
1 parent 817b066 commit ea0e8e9
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2017 The Depan Project Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.devtools.depan.eclipse.visualization.ogl;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Provide a common logger for the OGL rendering layer.
* Simply import this class, and use the available {@link #LOG} member.
*
* @author <a href="mailto:leeca@pnambic.com">Lee Carver</a>
*/
public class GLLogger {

public static final Logger LOG =
Logger.getLogger(GLLogger.class.getName());

private GLLogger() {
// Prevent instantiation.
}

/**
* Bizarre that this is not part of standard java.util.logging.
*/
public static final void logException(String msg, Throwable err) {
LOG.log(Level.SEVERE, msg, err);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,28 @@ protected void drawScene(float elapsedTime) {
}
}


/**
* Draw the pickable elements in the scene.
* No updates for rendering metrics.
* Scene management is not required.
*
* [2017] Omit non-pickable edges for faster rendering and better pick
* resolution on busy diagrams.
*/
@Override
protected void drawPickables() {
super.drawPickables(); // clean up, setup background, camera, etc....
renderer.preFrame(0.0f);

// only draw nodes
for (NodeRenderingProperty p : nodesProperties) {
renderer.render(p);
}

renderer.postFrame();
}

@Override
public void uncaughtKey(KeyEvent event,
boolean keyCtrlState, boolean keyAltState, boolean keyShiftState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,28 @@
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.nio.IntBuffer;
import java.util.logging.Logger;

/**
* An abstract GLScene. Handling OpenGL specific details.
*
* @author Yohann Coppel
*/
public abstract class GLScene {
private static final double ZOOM_BASE = 100.0;

private static final double ZOOM_BASE = 100.0;
private static final int[] EMPTY_HIT_LIST = new int[0];

private static final Logger logger =
Logger.getLogger(GLScene.class.getName());

// For OSX, get profile early
private static GLProfile DEFAULT_PROFILE = GLProfile.getDefault();

private GLCanvas canvas;
private final GLContext context;
public final GL2 gl;
public final GLU glu;
private final SceneGrip grip;
private final double dpiScale;

// Can't be final, need to dispose
private GLCanvas canvas;

/** eye position */
private float xoff;
Expand Down Expand Up @@ -122,6 +121,7 @@ public GLScene(Composite parent) {
canvas.setCurrent();

context = createGLContext();
dpiScale = getDPIScale();

GL rawGL = context.getGL();
if (rawGL.isGL2()) {
Expand Down Expand Up @@ -166,13 +166,15 @@ public void widgetDisposed(DisposeEvent e) {
private GLContext createGLContext() {

try {
logger.info("Create context...");
GLLogger.LOG.info("Create context...");
GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory(DEFAULT_PROFILE);
GLContext result = drawableFactory.createExternalGLContext();
logger.info(" Done.");
GLLogger.LOG.info(" Done.");

return result;
} catch (Throwable errGl) {
GLLogger.logException(
"Unable to create GL Context", errGl);
errGl.printStackTrace();
throw new RuntimeException(errGl);
}
Expand All @@ -183,11 +185,10 @@ protected void resizeScene() {
context.makeCurrent();

Rectangle rect = canvas.getClientArea();
double scale = getDPIScale();

gl.glViewport(0, 0,
(int) (rect.width * scale),
(int) (rect.height * scale));
(int) (rect.width * dpiScale),
(int) (rect.height * dpiScale));

gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
Expand Down Expand Up @@ -216,12 +217,21 @@ private double getDPIScale() {
int zoomVal = Integer.parseInt(zoomText);
return zoomVal / ZOOM_BASE;
} catch (NumberFormatException errNumb) {
logger.warning("Bad DPI scaling term " + zoomText
GLLogger.LOG.warning(
"Bad DPI scaling term " + zoomText
+ ". Using 1.0 for OGL scaling");
}
return 1.0;
}

private int scaleDpiUp(int swtCoord) {
// Skip autoboxing, etc., for easy case.
if (dpiScale == 1.0) {
return swtCoord;
}
return (int) (dpiScale * swtCoord);
}

private void updateViewpoint(Rectangle rect) {
int width = rect.width;
int height = Math.max(rect.height, 1);
Expand Down Expand Up @@ -287,6 +297,24 @@ public void prepareResources() {
protected void allocateResources() {
}

/////////////////////////////////////
// Draw the scene

/**
* Clear the scene and adjust the camera position.
*
* Hook method for derived types to render the image. Extending types
* should call the super-method first to establish a clear image and
* the proper grip.
*
* @param elapsedTime time since previous frame.
*/
protected void drawScene(float elapsedTime) {
step();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
prepareCamera();
}

/**
* @param elapsedTime time since previous frame.
*/
Expand All @@ -305,6 +333,21 @@ public void render(float elapsedTime) {
context.release();
}

/////////////////////////////////////
// Element picking

/**
* Clear the scene and adjust the camera position for element picking.
*
* Hook method for derived types to render the pickable elements in the
* diagram. Derived types should call the super-method first to establish
* a clear image and the proper grip.
*/
protected void drawPickables() {
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
prepareCamera();
}

private int[] renderWithPicking() {
if (!canvas.isCurrent()) {
canvas.setCurrent();
Expand All @@ -329,7 +372,7 @@ private int[] renderWithPicking() {
selectionHeight, viewPort, 0);
updateViewpoint(canvas.getClientArea());

drawScene(0f);
drawPickables();

gl.glPopMatrix();
gl.glFlush();
Expand Down Expand Up @@ -395,11 +438,11 @@ public void moveToPosition(float camX, float camY) {
public void zoomToCamera(float zOffset) {
if (zOffset > (GLConstants.Z_FAR - 1.0f)) {
zOffset = GLConstants.Z_FAR - 1.0f;
logger.info("clamped zoom at " + zOffset);
GLLogger.LOG.info("clamped zoom at " + zOffset);
}
if (zOffset < (GLConstants.ZOOM_MAX)) {
zOffset = GLConstants.ZOOM_MAX;
logger.info("clamped zoom at " + zOffset);
GLLogger.LOG.info("clamped zoom at " + zOffset);
}

targetZoff = zOffset;
Expand Down Expand Up @@ -596,8 +639,6 @@ private boolean isEpsilon(float left, float right, float epsilon) {
* Establish the position and direction of the camera.
*/
private void prepareCamera() {
step();

if (!GLScene.hyperbolic) {
// logger.info("position: " + xoff + ", " + yoff + ", " + zoff);
// logger.info("rotation: " + xrot + ", " + yrot + ", " + zrot);
Expand All @@ -612,26 +653,9 @@ private void prepareCamera() {
//gl.glRotatef(this.yrot, 0.0f, 1.0f, 0.0f);
}

/////////////////////////////////////
// Draw the scene

/**
* Clear the scene and adjust the camera position.
*
* Hook method for derived types to render the image. Extending types
* should call the super-method first to establish a clear image and
* the proper grip.
*
* @param elapsedTime time since previous frame.
*/
protected void drawScene(float elapsedTime) {
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
prepareCamera();
}

public void printMousePos(int x, int y) {
double[] m = getOGLPos(x, y);
logger.info("Mouse " + m[0] + " : " + m[1] + " - " + m[2]);
GLLogger.LOG.info("Mouse " + m[0] + " : " + m[1] + " - " + m[2]);
}

/**
Expand Down Expand Up @@ -828,7 +852,7 @@ private void logUncaughtKey(int keyCode, char character,
}

buf.append(")");
logger.info(buf.toString());
GLLogger.LOG.info(buf.toString());
}

/**
Expand All @@ -843,7 +867,7 @@ private int[] processHits(int hits, IntBuffer buffer) {
return EMPTY_HIT_LIST;
}
if (hits < 0) {
logger.warning("Too many hits!!" +
GLLogger.LOG.warning("Too many hits!!" +
" IntBuffer capacity = " + buffer.capacity());
return EMPTY_HIT_LIST;
}
Expand All @@ -862,21 +886,21 @@ private int[] processHits(int hits, IntBuffer buffer) {
offset++;
}
}
logger.fine("hits = " + hits + "; offset = " + offset);
GLLogger.LOG.fine("hits = " + hits + "; offset = " + offset);
return hitsResults;
}

/**
* Pick the object at the given mouse position (in window-relative
* coordinates)
*
* @param mouseX
* @param mouseY
* @param mouseX - SWT mouse coordinates
* @param mouseY - SWT mouse coordinates
* @return ids of picked objects.
*/
public int[] pickObjectsAt(int mouseX, int mouseY) {
this.mouseX = mouseX;
this.mouseY = mouseY;
this.mouseX = scaleDpiUp(mouseX);
this.mouseY = scaleDpiUp(mouseY);
this.selectionWidth = 1;
this.selectionHeight = 1;
return renderWithPicking();
Expand All @@ -885,13 +909,20 @@ public int[] pickObjectsAt(int mouseX, int mouseY) {
/**
* The same as pickObjectAt, but with a rectangle.
*
* @param startX
* @param startY
* @param toX
* @param toY
* @param startX - SWT mouse coordinates
* @param startY - SWT mouse coordinates
* @param toX - SWT mouse coordinates
* @param toY - SWT mouse coordinates
* @return ids of picked objects.
*/
public int[] pickRectangle(int startX, int startY, int toX, int toY) {

// Convert from SWT to OGL coordinates first
startX = scaleDpiUp(startX);
startY = scaleDpiUp(startY);
toX = scaleDpiUp(toX);
toY = scaleDpiUp(toY);

if (startX < toX) {
this.selectionWidth = toX - startX;
this.mouseX = startX + selectionWidth / 2;
Expand All @@ -913,18 +944,18 @@ public int[] pickRectangle(int startX, int startY, int toX, int toY) {
/**
* Activate and define an overlay rectangle that shows the selection area.
*
* @param fromX
* @param fromY
* @param mouseX
* @param mouseY
* @param fromX - SWT mouse coordinates
* @param fromY - SWT mouse coordinates
* @param mouseX - SWT mouse coordinates
* @param mouseY - SWT mouse coordinates
*/
public void activateSelectionRectangle(
int fromX, int fromY, int mouseX, int mouseY) {
drawSelectRectangle = true;
this.mouseX = mouseX;
this.mouseY = mouseY;
this.startSelectX = fromX;
this.startSelectY = fromY;
this.mouseX = scaleDpiUp(mouseX);
this.mouseY = scaleDpiUp(mouseY);
this.startSelectX = scaleDpiUp(fromX);
this.startSelectY = scaleDpiUp(fromY);
}

/**
Expand Down

0 comments on commit ea0e8e9

Please sign in to comment.