/*******************************************************************************
* This file is part of Goko.
*
* Goko is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Goko is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Goko. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package org.goko.tools.viewer.jogl.service;
import javax.media.opengl.GLAutoDrawable;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.goko.core.common.exception.GkException;
import org.goko.core.common.measure.quantity.Length;
import org.goko.core.config.GokoPreference;
import org.goko.core.controller.IFourAxisControllerAdapter;
import org.goko.core.controller.IGCodeContextProvider;
import org.goko.core.controller.IJogService;
import org.goko.core.controller.IThreeAxisControllerAdapter;
import org.goko.core.controller.IWorkVolumeProvider;
import org.goko.core.controller.ThreeToFourAxisAdapterWrapper;
import org.goko.core.controller.listener.IWorkVolumeUpdateListener;
import org.goko.core.gcode.rs274ngcv3.context.GCodeContext;
import org.goko.core.log.GkLog;
import org.goko.core.math.Tuple6b;
import org.goko.tools.viewer.jogl.GokoJoglCanvas;
import org.goko.tools.viewer.jogl.camera.orthographic.FrontCamera;
import org.goko.tools.viewer.jogl.camera.orthographic.LeftCamera;
import org.goko.tools.viewer.jogl.preferences.JoglViewerPreference;
import org.goko.tools.viewer.jogl.service.overlay.KeyboardJogOverlay;
import org.goko.tools.viewer.jogl.utils.render.coordinate.FourAxisOriginRenderer;
import org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer;
import org.goko.tools.viewer.jogl.utils.render.tool.ToolLinePrintRenderer;
import org.goko.tools.viewer.jogl.utils.render.tool.ToolRenderer;
/**
* Jogl implementation of the viewer service
*
* @author PsyKo
*
*/
public class JoglViewerServiceImpl extends JoglSceneManager implements IJoglViewerService, IPropertyChangeListener, IWorkVolumeUpdateListener{
/** LOG */
private static final GkLog LOG = GkLog.getLogger(JoglViewerServiceImpl.class);
/** SERVICE_ID */
private static final String SERVICE_ID = "org.goko.viewer.jogl";
/** Jog service */
private IJogService jogService;
/** Work volume provider */
private IWorkVolumeProvider workVolumeProvider;
/** Bind camera on tool position ? */
private boolean lockCameraOnTool;
private IGridRenderer xyGridRenderer;
private IGridRenderer xzGridRenderer;
private IGridRenderer yzGridRenderer;
private FourAxisOriginRenderer zeroRenderer;
private KeyboardJogAdatper keyboardJogAdapter;
private ToolRenderer toolRenderer;
private IFourAxisControllerAdapter controllerAdapter;
private IGCodeContextProvider<GCodeContext> gcodeContextProvider;
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#getServiceId()
*/
@Override
public String getServiceId() throws GkException {
return SERVICE_ID;
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#start()
*/
@Override
public void start() throws GkException {
LOG.info("Starting "+getServiceId());
JoglViewerPreference.getInstance().addPropertyChangeListener(this);
GokoPreference.getInstance().addPropertyChangeListener(this);
zeroRenderer = new FourAxisOriginRenderer(JoglViewerPreference.getInstance().isRotaryAxisEnabled());
addRenderer(zeroRenderer);
this.xyGridRenderer = JoglUtils.drawXYGrid(gcodeContextProvider);
this.xzGridRenderer = JoglUtils.drawXZGrid(gcodeContextProvider);
this.yzGridRenderer = JoglUtils.drawYZGrid(gcodeContextProvider);
this.toolRenderer = new ToolRenderer();
this.toolRenderer.setGcodeContextProvider(gcodeContextProvider);
this.toolRenderer.setControllerAdapter(controllerAdapter);
addRenderer(toolRenderer);
addRenderer(new ToolLinePrintRenderer(controllerAdapter, gcodeContextProvider));
updateGridRenderer(xyGridRenderer);
updateGridRenderer(xzGridRenderer);
updateGridRenderer(yzGridRenderer);
addRenderer(xyGridRenderer);
addRenderer(xzGridRenderer);
addRenderer(yzGridRenderer);
if(workVolumeProvider != null){
workVolumeProvider.addUpdateListener(this);
}
LOG.info("Successfully started " + getServiceId());
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#stop()
*/
@Override
public void stop() throws GkException {
}
/**
* @param controllerService the controllerService to set
*/
public void setControllerAdapter(IThreeAxisControllerAdapter controllerService) throws GkException {
if(controllerService instanceof IFourAxisControllerAdapter){
setControllerAdapter((IFourAxisControllerAdapter)controllerService);
}else{
setControllerAdapter(new ThreeToFourAxisAdapterWrapper(controllerService));
}
}
/**
* @param controllerService the controllerService to set
* @throws GkException GkException
*/
public void setControllerAdapter(IFourAxisControllerAdapter controllerService) throws GkException {
this.controllerAdapter = controllerService;
}
/** (inheritDoc)
* @see javax.media.opengl.GLEventListener#dispose(javax.media.opengl.GLAutoDrawable)
*/
@Override
public void dispose(GLAutoDrawable arg0) {
}
/**
* @return the lockCameraOnTool
*/
@Override
public boolean isLockCameraOnTool() {
return lockCameraOnTool;
}
/**
* @param lockCameraOnTool the lockCameraOnTool to set
*/
@Override
public void setLockCameraOnTool(boolean lockCameraOnTool) {
this.lockCameraOnTool = lockCameraOnTool;
}
/**
* @return the continuousJogService
*/
public IJogService getJogService() {
return jogService;
}
/**
* @param continuousJogService the continuousJogService to set
*/
public void setJogService(IJogService continuousJogService) {
this.jogService = continuousJogService;
}
/** (inheritDoc)
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
super.propertyChange(event);
try {
zeroRenderer.setDisplayRotaryAxis(JoglViewerPreference.getInstance().isRotaryAxisEnabled());
zeroRenderer.setRotationAxis(JoglViewerPreference.getInstance().getRotaryAxisDirection());
zeroRenderer.update();
// Update the grid
if(StringUtils.startsWith(event.getProperty(), JoglViewerPreference.GROUP_GRID)
|| StringUtils.startsWith(event.getProperty(), GokoPreference.KEY_DISTANCE_UNIT)){
boolean xyDisplay = xyGridRenderer.isEnabled();
boolean xzDisplay = xzGridRenderer.isEnabled();
boolean yzDisplay = yzGridRenderer.isEnabled();
this.xyGridRenderer.destroy();
this.xzGridRenderer.destroy();
this.yzGridRenderer.destroy();
this.xyGridRenderer = JoglUtils.drawXYGrid(gcodeContextProvider);
this.xzGridRenderer = JoglUtils.drawXZGrid(gcodeContextProvider);
this.yzGridRenderer = JoglUtils.drawYZGrid(gcodeContextProvider);
updateGridRenderer(xyGridRenderer);
updateGridRenderer(xzGridRenderer);
updateGridRenderer(yzGridRenderer);
xyGridRenderer.setEnabled(xyDisplay);
xzGridRenderer.setEnabled(xzDisplay);
yzGridRenderer.setEnabled(yzDisplay);
addRenderer(xyGridRenderer);
addRenderer(xzGridRenderer);
addRenderer(yzGridRenderer);
}
} catch (GkException e) {
LOG.error(e);
}
}
/** (inheritDoc)
* @see org.goko.tools.viewer.jogl.service.JoglSceneManager#setActiveCamera(java.lang.String)
*/
@Override
public void setActiveCamera(String idCamera) throws GkException {
super.setActiveCamera(idCamera);
if(xyGridRenderer != null){
setRendererEnabled(JoglUtils.XY_GRID_ID, false);
setRendererEnabled(JoglUtils.XZ_GRID_ID, false);
setRendererEnabled(JoglUtils.YZ_GRID_ID, false);
if(StringUtils.equals(idCamera, FrontCamera.ID)){
setRendererEnabled(JoglUtils.XZ_GRID_ID, true);
}else if(StringUtils.equals(idCamera, LeftCamera.ID)){
setRendererEnabled(JoglUtils.YZ_GRID_ID, true);
}else{
setRendererEnabled(JoglUtils.XY_GRID_ID, true);
}
}
}
/** (inheritDoc)
* @see org.goko.tools.viewer.jogl.service.IJoglViewerService#zoomToFit()
*/
@Override
public void zoomToFit() throws GkException {
super.zoomToFit();
}
/** (inheritDoc)
* @see org.goko.tools.viewer.jogl.service.JoglSceneManager#onCanvasCreated(org.goko.tools.viewer.jogl.GokoJoglCanvas)
*/
@Override
protected void onCanvasCreated(GokoJoglCanvas canvas) throws GkException {
if(jogService != null){
this.keyboardJogAdapter = new KeyboardJogAdatper(getCanvas(), jogService);
canvas.addKeyListener( keyboardJogAdapter );
addOverlayRenderer(new KeyboardJogOverlay(canvas, keyboardJogAdapter));
}
}
private void updateGridRenderer(IGridRenderer gridRenderer) throws GkException{
Tuple6b workMin = null;
Tuple6b workMax = null;
if(JoglViewerPreference.getInstance().isUseWorkVolumeProvider()
&& workVolumeProvider != null
&& workVolumeProvider.findWorkVolumeMinimalPosition() != null
&& workVolumeProvider.findWorkVolumeMaximalPosition() != null
&& workVolumeProvider.findWorkVolumeMinimalPosition().distance(workVolumeProvider.findWorkVolumeMaximalPosition()).greaterThan(Length.ZERO)){
workMin = workVolumeProvider.getWorkVolumeMinimalPosition();
workMax = workVolumeProvider.getWorkVolumeMaximalPosition();
}else{
workMin = JoglViewerPreference.getInstance().getGridStart();
workMax = JoglViewerPreference.getInstance().getGridEnd();
}
gridRenderer.setWorldBounds(workMin, workMax);
gridRenderer.setMajorIncrement( JoglViewerPreference.getInstance().getMajorGridSpacing());
gridRenderer.setMinorIncrement( JoglViewerPreference.getInstance().getMinorGridSpacing());
gridRenderer.setMajorUnitColor( JoglViewerPreference.getInstance().getMajorColor());
gridRenderer.setMinorUnitColor( JoglViewerPreference.getInstance().getMinorColor());
gridRenderer.setMinorOpacity(JoglViewerPreference.getInstance().getMinorGridOpacity());
gridRenderer.setMajorOpacity(JoglViewerPreference.getInstance().getMajorGridOpacity());
gridRenderer.setAxisOpacity(JoglViewerPreference.getInstance().getAxisGridOpacity());
gridRenderer.update();
}
/**
* @return the workVolumeProvider
*/
public IWorkVolumeProvider getWorkVolumeProvider() {
return workVolumeProvider;
}
/**
* @param workVolumeProvider the workVolumeProvider to set
*/
public void setWorkVolumeProvider(IWorkVolumeProvider workVolumeProvider) {
this.workVolumeProvider = workVolumeProvider;
}
/**
* @return the gcodeContextProvider
*/
public IGCodeContextProvider<GCodeContext> getGcodeContextProvider() {
return gcodeContextProvider;
}
/**
* @param gcodeContextProvider the gcodeContextProvider to set
*/
public void setGcodeContextProvider(IGCodeContextProvider<GCodeContext> gcodeContextProvider) {
this.gcodeContextProvider = gcodeContextProvider;
}
/** (inheritDoc)
* @see org.goko.core.controller.listener.IWorkVolumeUpdateListener#onWorkVolumeUpdate()
*/
@Override
public void onWorkVolumeUpdate() {
try{
updateGridRenderer(xyGridRenderer);
updateGridRenderer(xzGridRenderer);
updateGridRenderer(yzGridRenderer);
}catch(GkException e){
LOG.error(e);
}
}
}