--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.awt.event.MouseEvent;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IMenuListener;\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.jface.action.MenuManager;\r
+import org.eclipse.jface.action.Separator;\r
+import org.eclipse.jface.dialogs.MessageDialog;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.swt.events.PaintEvent;\r
+import org.eclipse.swt.events.PaintListener;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.ui.IActionBars;\r
+import org.eclipse.ui.ISharedImages;\r
+import org.eclipse.ui.IWorkbenchActionConstants;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.internal.WorkbenchWindow;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.events.GraphChangeEvent;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.actions.CameraAction;\r
+import org.simantics.proconf.g3d.actions.ContextAction;\r
+import org.simantics.proconf.g3d.actions.InteractiveAction;\r
+import org.simantics.proconf.g3d.base.SelectionAdapter.SelectionType;\r
+import org.simantics.proconf.g3d.common.JmeComposite;\r
+import org.simantics.proconf.g3d.common.JmeSinglePassRenderingComponent;\r
+import org.simantics.proconf.g3d.common.OrbitalCamera;\r
+import org.simantics.proconf.g3d.dialogs.JMEDialog;\r
+import org.simantics.proconf.g3d.dnd.ShapeDropTarget;\r
+import org.simantics.proconf.g3d.gizmo.Gizmo;\r
+import org.simantics.proconf.g3d.input.InputProvider;\r
+import org.simantics.proconf.g3d.input.SWTInputProvider;\r
+import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.tools.ScenegraphLockTraverser;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.jface.MenuTools;\r
+\r
+import com.jme.math.Ray;\r
+import com.jme.math.Vector2f;\r
+import com.jme.math.Vector3f;\r
+import com.jme.renderer.ColorRGBA;\r
+\r
+\r
+public abstract class ThreeDimensionalEditorBase implements Runnable {\r
+\r
+ private Resource inputResource;\r
+ \r
+ private List<EditorContribution> editorContributions = new ArrayList<EditorContribution>();\r
+ \r
+ private EditorContribution currentEditorContribution;\r
+ \r
+ protected List<ContextAction> actions = new ArrayList<ContextAction>();\r
+ \r
+ private List<Action> contributionSelectionActions = new ArrayList<Action>();\r
+ \r
+ protected Composite parent;\r
+ \r
+ protected ISessionContext sessionContext;\r
+ \r
+ protected Session session;\r
+ \r
+ protected ScenegraphAdapter adapter;\r
+ \r
+ protected SelectionAdapter selectionAdapter;\r
+ \r
+ protected Action refreshAction;\r
+ \r
+ protected Action configureJMEAction;\r
+ \r
+ private Action lockScenegraphAction;\r
+\r
+ protected Menu contextMenu;\r
+\r
+ private JmeComposite renderingComposite = null; \r
+\r
+ protected OrbitalCamera camera = new OrbitalCamera();\r
+\r
+ protected boolean viewChanged = true;\r
+\r
+ private InteractiveAction currentAction = null;\r
+ \r
+ private Gizmo currentGizmo = null;\r
+ \r
+ private InteractiveAction cameraAction = null;\r
+ \r
+ private JmeRenderingComponent component = null;\r
+ \r
+ protected InputProvider input = null;\r
+ \r
+ protected ShapeDropTarget dropTarget;\r
+\r
+// protected IEditorActionBarContributor actionBarContributor;\r
+ protected IActionBars actionBars;\r
+ protected IToolBarManager toolBarManager;\r
+ protected IMenuManager menuManager;\r
+ \r
+ public ThreeDimensionalEditorBase(ISessionContext session) {\r
+ this.sessionContext = session;\r
+ this.session = session.getSession();\r
+ component = new JmeSinglePassRenderingComponent();\r
+ }\r
+\r
+ public ThreeDimensionalEditorBase(ISessionContext session, JmeRenderingComponent component) {\r
+ this.sessionContext = session;\r
+ this.session = session.getSession();\r
+ this.component = component;\r
+ }\r
+ \r
+ protected void setRenderingComponent(JmeRenderingComponent component) {\r
+ assert(renderingComposite == null); // ensure that this is called before initialization\r
+ this.component = component;\r
+ }\r
+ \r
+// public void setActionBarContributor(IEditorActionBarContributor contributor) {\r
+// actionBarContributor = contributor;\r
+// }\r
+ \r
+ public void setActionBars(IActionBars actionBars) {\r
+ this.actionBars = actionBars;\r
+ this.menuManager = actionBars.getMenuManager();\r
+ this.toolBarManager = actionBars.getToolBarManager();\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ public ISessionContext getSessionContext() {\r
+ return sessionContext;\r
+ }\r
+ \r
+ public Session getSession() {\r
+ return session;\r
+ }\r
+ \r
+ /**\r
+ * Creates basic UI for ThreeDimenionalEditors.\r
+ * Note : inputResource has not been set at this point.\r
+ * \r
+ * @param graph\r
+ * @param parent\r
+ */\r
+ public void createControl(Graph graph, Composite parent) {\r
+ this.parent = parent;\r
+ renderingComposite = new JmeComposite(parent,component);\r
+ // add listeners to force repaint on size changes\r
+ renderingComposite.getCanvas().addPaintListener(new PaintListener() {\r
+ public void paintControl(PaintEvent e) {\r
+ viewChanged = true; \r
+ }\r
+ });\r
+\r
+ \r
+ input = new SWTInputProvider();\r
+ \r
+ renderingComposite.initGL();\r
+ camera.setCamera(component.getCamera());\r
+ camera.updateCamera(); \r
+ makeActions(graph);\r
+ hookContextMenu();\r
+\r
+ // provide selection events for properies view\r
+ this.adapter = createScenegraphAdapter();\r
+ this.selectionAdapter = createSelectionAdapter();\r
+ \r
+ this.selectionAdapter.addSelectionChangedListener(new ISelectionChangedListener() {\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ setCurrentAction(getDefaultAction()); \r
+ }\r
+ });\r
+ hookDragAndDrop(); \r
+ hookInput();\r
+ VisualizationScheduler.getInstance().addVisualization(this);\r
+ \r
+ if (editorContributions.size() > 0) {\r
+ // setActiveEditorContribution(editorContributions.get(0));\r
+ // } else if (editorContributions.size() > 1) {\r
+ // create actions for selecting contribution\r
+ for (EditorContribution ec : editorContributions) {\r
+ final EditorContribution e = ec;\r
+ Action a = new Action(e.getName(),Action.AS_RADIO_BUTTON) {\r
+ @Override\r
+ public void run() {\r
+ \r
+ setActiveEditorContribution(e);\r
+ }\r
+ };\r
+ contributionSelectionActions.add(a);\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ public void addEditorContribution(EditorContribution e) {\r
+ if (parent != null)\r
+ throw new RuntimeException("Editor contributions must be added before editor is created.");\r
+ editorContributions.add(e);\r
+ }\r
+ \r
+ private void initializeEditorContributions(Graph graph) {\r
+ for (EditorContribution e : editorContributions) {\r
+ e.initialize(graph);\r
+ }\r
+ if (editorContributions.size() > 0)\r
+ parent.getDisplay().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ setActiveEditorContribution(editorContributions.get(0));\r
+ }\r
+ }); \r
+ }\r
+ \r
+ \r
+ private void hookInput() {\r
+ renderingComposite.getCanvas().addKeyListener((SWTInputProvider) input);\r
+ renderingComposite.getCanvas().addMouseListener((SWTInputProvider) input);\r
+ renderingComposite.getCanvas().addMouseMoveListener((SWTInputProvider) input);\r
+ renderingComposite.getCanvas().addMouseTrackListener((SWTInputProvider) input);\r
+ renderingComposite.getCanvas().addFocusListener((SWTInputProvider) input);\r
+ }\r
+ \r
+ protected abstract ScenegraphAdapter createScenegraphAdapter();\r
+ protected abstract SelectionAdapter createSelectionAdapter();\r
+\r
+ \r
+ public JmeComposite getRenderingComposite() {\r
+ return renderingComposite;\r
+ }\r
+ \r
+ public JmeRenderingComponent getRenderingComponent() {\r
+ return component;\r
+ }\r
+\r
+ public ScenegraphAdapter getScenegraphAdapter() {\r
+ return adapter;\r
+ }\r
+ \r
+ public SelectionAdapter getSelectionAdapter() {\r
+ return selectionAdapter;\r
+ }\r
+\r
+ public OrbitalCamera getCamera() {\r
+ return camera;\r
+ }\r
+ \r
+ public void setViewChanged(boolean b) {\r
+ viewChanged = b;\r
+ }\r
+\r
+ protected void hookContextMenu() {\r
+ MenuManager menuMgr = new MenuManager("#PopupMenu");\r
+ menuMgr.setRemoveAllWhenShown(true);\r
+ menuMgr.addMenuListener(new IMenuListener() {\r
+ public void menuAboutToShow(IMenuManager manager) {\r
+ final IMenuManager m = manager;\r
+ GraphRequestAdapter r = new GraphRequestAdapter() {\r
+ @Override\r
+ public GraphRequestStatus perform(Graph g) throws Exception {\r
+ ThreeDimensionalEditorBase.this.fillContextMenu(g,m);\r
+ return GraphRequestStatus.transactionComplete();\r
+ }\r
+ };\r
+ \r
+ session.syncRead(r);\r
+ \r
+ }\r
+ });\r
+\r
+ contextMenu = menuMgr.createContextMenu(renderingComposite);\r
+ }\r
+\r
+ \r
+\r
+ protected void fillContextMenu(Graph graph,IMenuManager manager) {\r
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));\r
+ \r
+ List<Resource> selected = selectionAdapter.getSelectedResources();\r
+ for (ContextAction action : actions) {\r
+ if(action.usable(graph,selected)) {\r
+ manager.add(action);\r
+ }\r
+ }\r
+ if (currentEditorContribution != null) {\r
+ currentEditorContribution.fillContextMenu(graph, manager, selectionAdapter.getCurrentSelection());\r
+ for (ContextAction action : currentEditorContribution.getActions()) {\r
+ if(action.usable(graph,selected)) {\r
+ manager.add(action);\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ protected void fillLocalToolBar() {\r
+\r
+ if (currentEditorContribution != null)\r
+ currentEditorContribution.fillLocalToolBar(toolBarManager);\r
+ }\r
+ \r
+ protected void fillLocalPullDown() {\r
+ for (Action a : contributionSelectionActions) {\r
+ IMenuManager menu = MenuTools.getOrCreate(getMenuID(),"View", menuManager);\r
+ menu.add(a);\r
+ }\r
+ MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(refreshAction);\r
+ if (configureJMEAction != null) {\r
+ MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(configureJMEAction);\r
+ }\r
+\r
+ MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(lockScenegraphAction);\r
+ if (currentEditorContribution != null)\r
+ currentEditorContribution.fillLocalPullDown(menuManager);\r
+ }\r
+ \r
+ public String getMenuID() {\r
+ return Long.toString(getInputResource().getResourceId());\r
+ }\r
+\r
+ protected void makeActions(Graph graph) {\r
+ \r
+ refreshAction = new Action() {\r
+\r
+ public void run() {\r
+ GraphRequestAdapter r = new GraphRequestAdapter() {\r
+ public GraphRequestStatus perform(Graph g) throws Exception {\r
+// Stack<IGraphicsNode> stack = new Stack<IGraphicsNode>();\r
+// stack.push(adapter.getNode(adapter.getRootResource()));\r
+// while(!stack.isEmpty()) {\r
+// IGraphicsNode node = stack.pop();\r
+// stack.addAll(node.getChildren());\r
+// if (node instanceof IGeometryNode) {\r
+// ((IGeometryNode)node).updateGeometry(g);\r
+// }\r
+// }\r
+ for (IGraphicsNode node : adapter.getNodes())\r
+ if (node instanceof IGeometryNode)\r
+ ((IGeometryNode)node).updateGeometry(g);\r
+ viewChanged = true;\r
+ return GraphRequestStatus.transactionComplete();\r
+ };\r
+ };\r
+ session.asyncRead(r);\r
+ \r
+ }\r
+ };\r
+ refreshAction.setText("Refresh");\r
+ refreshAction.setToolTipText("Refreshes the visualization");\r
+ refreshAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(\r
+ ISharedImages.IMG_TOOL_UP));\r
+ if (getRenderingComponent() instanceof JmeSinglePassRenderingComponent) {\r
+ configureJMEAction = new Action() {\r
+ public void run() {\r
+ JmeSinglePassRenderingComponent c = (JmeSinglePassRenderingComponent)getRenderingComponent();\r
+ JMEDialog dialog = new JMEDialog(ThreeDimensionalEditorBase.this.parent.getShell());\r
+ c.getDisplaySystem().setCurrent();\r
+ dialog.setBounds(c.isShowBounds());\r
+ dialog.setNormals(c.isShowNormals());\r
+ dialog.setWireframe(c.isShowWireframe());\r
+ ColorRGBA col = c.getDisplaySystem().getRenderer().getBackgroundColor();\r
+ dialog.setFloatColor(new float[]{col.r,col.g,col.b});\r
+ if (dialog.open() == JMEDialog.CANCEL)\r
+ return;\r
+ c.setShowBounds(dialog.isBounds());\r
+ c.setShowNormals(dialog.isNormals());\r
+ c.setShowWireframe(dialog.isWireframe());\r
+ if (dialog.getFloatColor() != null) {\r
+ c.getDisplaySystem().setCurrent();\r
+ c.getDisplaySystem().getRenderer().setBackgroundColor(new ColorRGBA(dialog.getFloatColor()[0],dialog.getFloatColor()[1],dialog.getFloatColor()[2],0.f));\r
+ }\r
+ }\r
+ };\r
+ configureJMEAction.setText("Configure JME");\r
+ configureJMEAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("fi.vtt.proconf.ode", "icons/silk/wrench.png"));\r
+ }\r
+ \r
+ lockScenegraphAction = new Action("Lock scenegraph",Action.AS_CHECK_BOX) {\r
+ public void run() {\r
+ new ScenegraphLockTraverser(adapter.getRoot(),this.isChecked());\r
+ }\r
+ };\r
+ \r
+ cameraAction = new CameraAction(this); \r
+ currentAction = cameraAction;\r
+ \r
+ \r
+ }\r
+ \r
+ public InteractiveAction getDefaultAction() {\r
+ return cameraAction;\r
+ }\r
+ \r
+ public void createPickRay(Vector3d o, Vector3d d) {\r
+ Ray r = createPickRay();\r
+ o.x = r.origin.x;\r
+ o.y = r.origin.y;\r
+ o.z = r.origin.z;\r
+ d.x = r.direction.x;\r
+ d.y = r.direction.y;\r
+ d.z = r.direction.z;\r
+ d.normalize();\r
+ }\r
+ \r
+ public Ray createPickRay() {\r
+ Vector2f screenPos = new Vector2f();\r
+ screenPos.set(input.mouseX(),renderingComposite.getBounds().height - input.mouseY());\r
+ \r
+ \r
+ Ray mouseRay;\r
+ if (component.getCamera().isParallelProjection()) {\r
+ Vector3f worldCoords = renderingComposite.getDisplaySystem().getWorldCoordinates(screenPos, 0.0f);\r
+ mouseRay = new Ray(worldCoords,\r
+ component.getCamera().getDirection());\r
+ } else {\r
+ Vector3f worldCoords = renderingComposite.getDisplaySystem().getWorldCoordinates(screenPos, 1.0f);\r
+ mouseRay = new Ray(component.getCamera().getLocation(), worldCoords\r
+ .subtractLocal(component.getCamera().getLocation()));\r
+ }\r
+ return mouseRay;\r
+ }\r
+ \r
+ public Vector2f getScreenCoord(Tuple3d worldCoord) {\r
+ Vector3f v = renderingComposite.getDisplaySystem().getScreenCoordinates(VecmathJmeTools.get(worldCoord));\r
+ return new Vector2f(v.x,v.y);\r
+ }\r
+ \r
+ \r
+ public InputProvider getInputProvider() {\r
+ return input;\r
+ }\r
+\r
+ /**\r
+ * Changes current action \r
+ * \r
+ * @param type\r
+ */\r
+ public void setCurrentAction(InteractiveAction action) {\r
+ if (currentAction == action)\r
+ return;\r
+ if (toolBarManager != null) {\r
+ toolBarManager.removeAll();\r
+ fillLocalToolBar();\r
+ }\r
+ if (currentAction != null)\r
+ currentAction.deactivate();\r
+ currentAction = action;\r
+ if (currentAction != null) {\r
+ currentAction.activate();\r
+ if (toolBarManager != null) {\r
+ currentAction.fillToolBar(toolBarManager);\r
+ }\r
+ }\r
+ \r
+ updateBars();\r
+ }\r
+ \r
+ public InteractiveAction getCurrentAction() {\r
+ return currentAction;\r
+ }\r
+ \r
+ public void setActiveEditorContribution(EditorContribution contribution) {\r
+ if (currentEditorContribution == contribution)\r
+ return;\r
+ if (currentAction != getDefaultAction())\r
+ return;\r
+ if (currentEditorContribution != null)\r
+ currentEditorContribution.disposeControl();\r
+ currentEditorContribution = contribution;\r
+ int index = editorContributions.indexOf(contribution);\r
+ for (int i = 0; i < contributionSelectionActions.size(); i++) {\r
+ if (i != index)\r
+ contributionSelectionActions.get(i).setChecked(false);\r
+ else\r
+ contributionSelectionActions.get(i).setChecked(true);\r
+ }\r
+ if (currentEditorContribution != null)\r
+ currentEditorContribution.createControl(parent);\r
+ \r
+ actionBars.clearGlobalActionHandlers();\r
+ \r
+ parent.layout(true, true);\r
+ if (toolBarManager != null) {\r
+ toolBarManager.removeAll();\r
+ fillLocalToolBar();\r
+ }\r
+ if (menuManager != null) { \r
+ menuManager.removeAll();\r
+ fillLocalPullDown();\r
+ }\r
+ \r
+ updateBars();\r
+ }\r
+ \r
+ protected void updateBars() {\r
+ // TODO : actionBars.updateActionBars does not update toolbar, updating toolBar directly layouts code \r
+ // generated widgets top of contributed (extension) widgets. Only way to achieve proper update\r
+ // is to use WorkbenchWindow.getCoolBarManager.update(true)\r
+ actionBars.updateActionBars();\r
+// if (toolBarManager != null) {\r
+// toolBarManager.update(true);\r
+// }\r
+ WorkbenchWindow w = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();\r
+ w.getCoolBarManager().update(true);\r
+ }\r
+ \r
+ public void setGizmo(Gizmo gizmo) {\r
+ if (currentGizmo != null) {\r
+ currentGizmo.getNode().removeFromParent();\r
+ }\r
+ currentGizmo = gizmo;\r
+ selectionAdapter.setCurrentGizmo(gizmo);\r
+ viewChanged = true;\r
+ }\r
+ \r
+// public void setInfoText(String text) {\r
+// if (useInfoComposite) {\r
+// infoText.setText(text);\r
+// }\r
+// }\r
+\r
+ public void showMessage(String message) {\r
+ MessageDialog.openInformation(parent.getShell(), "Shape Editor", //$NON-NLS-1$\r
+ message);\r
+ }\r
+\r
+\r
+ /**\r
+ * Passing the focus request to the viewer's control.\r
+ */\r
+ public void setFocus() {\r
+ renderingComposite.getCanvas().setFocus();\r
+ }\r
+\r
+ public void dispose() {\r
+ //System.out.println("ThreeDimensionalEditorBase.dispose()");\r
+ VisualizationScheduler.getInstance().removeVisualization(this);\r
+\r
+ if (currentAction != null)\r
+ currentAction.deactivate();\r
+\r
+ for (EditorContribution e : editorContributions)\r
+ e.dispose();\r
+ \r
+ renderingComposite.dispose();\r
+\r
+ // copy of the set is needed to avoid ConcurrentModificationException\r
+ adapter.dispose();\r
+ component.dispose();\r
+ }\r
+\r
+ public final void reload(Graph g, Resource res) {\r
+ inputResource = res;\r
+ reloadFrom(EntityFactory.create(g, res));\r
+ // at this point we can initialize editor contributions, which may require inputResource\r
+ initializeEditorContributions(g);\r
+ }\r
+\r
+ public Resource getInputResource() {\r
+ return inputResource;\r
+ }\r
+ \r
+ public void update(GraphChangeEvent event) {\r
+// System.out.println("Transaction " + this + " : " + event.getTransactionId() + " Arg1: " + event.getArg1()\r
+// + " arg2: " + event.getArg2() + " sender: " + event.getSender() + " source: " + event.getSource());\r
+ \r
+// if (event.added.size() > 0) {\r
+// System.out.println("Added:");\r
+// for (Triplet t : event.added)\r
+// System.out.println(t);\r
+// }\r
+// if (event.changed.size() > 0) {\r
+// System.out.println("Changed:");\r
+// for (Triplet t : event.changed)\r
+// System.out.println(t);\r
+// }\r
+// if (event.removed.size() > 0) {\r
+// System.out.println("Removed:");\r
+// for (Triplet t : event.removed)\r
+// System.out.println(t);\r
+// }\r
+\r
+ }\r
+\r
+ \r
+\r
+ /**\r
+ * Loads the initial scene: all further updates to the view are done by\r
+ * listening changes in the shapes and int the shape group\r
+ * \r
+ * @param resource\r
+ */\r
+ protected abstract void reloadFrom(IEntity thing);\r
+\r
+\r
+ protected void viewUpdated() {\r
+\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see java.lang.Runnable#run()\r
+ */\r
+ public void run() {\r
+ if (currentEditorContribution != null)\r
+ currentEditorContribution.run();\r
+ if (parent.isDisposed() || !parent.isVisible())\r
+ return;\r
+ //renderingComposite.getDisplaySystem().setCurrent();\r
+ input.update();\r
+ if (input.mouseClicked()) {\r
+ int downMask = MouseEvent.CTRL_DOWN_MASK;\r
+\r
+ if ((input.clickModifiers() & downMask) > 0) {\r
+ selectionAdapter.setSelectionType(SelectionType.MODIFY);\r
+ } else {\r
+ selectionAdapter.setSelectionType(SelectionType.SET);\r
+ }\r
+ }\r
+ if (input.mouseMoved()) {\r
+ Ray mouseRay = createPickRay();\r
+ selectionAdapter.updateHighlights(mouseRay);\r
+ }\r
+ if (currentAction == cameraAction && input.mouseClicked()) {\r
+ selectionAdapter.pickHighlighted();\r
+ }\r
+ if (currentAction == cameraAction && input.mousePressed()\r
+ && (input.pressModifiers() & MouseEvent.BUTTON3_MASK) > 0) {\r
+ Point p = renderingComposite.toDisplay(input.mouseX(), input\r
+ .mouseY());\r
+ contextMenu.setLocation(p.x, p.y);\r
+ contextMenu.setVisible(true);\r
+ }\r
+\r
+ if (currentAction != null)\r
+ try {\r
+ currentAction.update();\r
+ } catch (Exception e) {\r
+ ErrorLogger.defaultLogError("Action error!", e);\r
+ setCurrentAction(getDefaultAction());\r
+ }\r
+\r
+ if (component.update())\r
+ viewChanged = true;\r
+ \r
+ if (!geometryUpdateRequestAdapter.isRunning() && adapter.needsUpdateGeometry()) {\r
+ session.asyncRead(geometryUpdateRequestAdapter); \r
+ }\r
+ \r
+ viewChanged |= adapter.isChanged();\r
+ if (viewChanged) {\r
+ viewChanged = false;\r
+ adapter.setChanged(false);\r
+ camera.updateCamera();\r
+ viewUpdated();\r
+ component.render();\r
+ }\r
+ }\r
+ // TODO : there is some sort of synchronization bug in rendering:\r
+ // part of the rendered objects are rendered with different camera transformation than others.\r
+ // re-rendering the scene hides the worst problems.\r
+ // Using shadows is the reason: shadowed objects are rendered with different transformation than non-shadowed.\r
+ //private boolean lastChanged = false;\r
+ \r
+ private GeometryUpdateRequestAdapter geometryUpdateRequestAdapter = new GeometryUpdateRequestAdapter();\r
+ \r
+ private class GeometryUpdateRequestAdapter extends GraphRequestAdapter {\r
+ private boolean running;\r
+ @Override\r
+ public GraphRequestStatus perform(Graph g) throws Exception {\r
+ running = true;\r
+ adapter.updateGeometry(g);\r
+ return GraphRequestStatus.transactionComplete();\r
+ }\r
+ @Override\r
+ public void requestCompleted(GraphRequestStatus status) {\r
+ running = false;\r
+ adapter.setChanged(true);\r
+ }\r
+ \r
+ public boolean isRunning() {\r
+ return running;\r
+ }\r
+ }\r
+\r
+ \r
+ \r
+ protected void hookDragAndDrop() {\r
+ dropTarget = new ShapeDropTarget(this);\r
+ }\r
+\r
+ /**\r
+ * Receives selection changes\r
+ * \r
+ * @param part\r
+ * @param selection\r
+ */\r
+ protected abstract void pageSelectionChanged(IWorkbenchPart part, ISelection selection);\r
+\r
+ /**\r
+ * EditorPart or ViewPart uses this method to forward getAdapter(Class)\r
+ * @see org.eclipse.ui.part.WorkbenchPart.getAdapter(Class adapter)\r
+ * @param adapter\r
+ * @return\r
+ */\r
+ public Object getAdapter(Class adapter) {\r
+ return null;\r
+ }\r
+\r
+}
\ No newline at end of file