package org.simantics.plant3d.gizmo; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import javax.vecmath.Point2d; import javax.vecmath.Vector3d; import org.simantics.g3d.scenegraph.RenderListener; import org.simantics.g3d.tools.PluginTools; import org.simantics.g3d.vtk.common.InteractiveVtkPanel; import org.simantics.g3d.vtk.gizmo.vtkGizmo; import org.simantics.g3d.vtk.utils.vtkUtil; import org.simantics.plant3d.Activator; import org.simantics.plant3d.scenegraph.InlineComponent; import org.simantics.plant3d.scenegraph.PipelineComponent; import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType; import vtk.vtkCellArray; import vtk.vtkFloatArray; import vtk.vtkPNGReader; import vtk.vtkPoints; import vtk.vtkPolyData; import vtk.vtkPolyDataMapper2D; import vtk.vtkPolygon; import vtk.vtkProp; import vtk.vtkRenderer; import vtk.vtkTexture; import vtk.vtkTexturedActor2D; public class TerminalSelectionGizmo extends vtkGizmo { vtkTexturedActor2D prevProp; vtkTexturedActor2D nextProp; vtkTexturedActor2D middleProp; boolean showPrev = false; boolean showNext = false; boolean showMiddle = false; Vector3d middle = new Vector3d(); Vector3d prev = new Vector3d(); Vector3d next = new Vector3d(); InteractiveVtkPanel panel; private RenderListener listener; public TerminalSelectionGizmo(InteractiveVtkPanel panel) { this.panel = panel; this.listener = new RenderListener() { @Override public void preRender() { if (showMiddle) { Point2d p = vtkUtil.getScreenCoordinates(getRenderer(), middle); middleProp.SetDisplayPosition((int)p.x, (int)p.y); } if (showPrev) { Point2d p = vtkUtil.getScreenCoordinates(getRenderer(), prev); prevProp.SetDisplayPosition((int)p.x, (int)p.y); } if (showNext) { Point2d p = vtkUtil.getScreenCoordinates(getRenderer(), next); nextProp.SetDisplayPosition((int)p.x, (int)p.y); } } @Override public void postRender() { } }; } @Override public void attach(Object renderingPart) { if (nextProp == null) { loadData(); } panel.addListener(listener); super.attach(renderingPart); } @Override public Collection getGizmo() { List list = new ArrayList(); if (showPrev) { list.add(prevProp); } if (showNext) { list.add(nextProp); } if (showMiddle) { list.add(middleProp); } return list; } protected void attachActors() { vtkRenderer ren = getRenderer(); if (showPrev) { ren.AddActor(prevProp); } if (showNext) { ren.AddActor(nextProp); } if (showMiddle) { ren.AddActor(middleProp); } } @Override protected void deattachActors() { panel.removeListener(listener); vtkRenderer ren = getRenderer(); ren.RemoveActor(prevProp); ren.RemoveActor(nextProp); ren.RemoveActor(middleProp); } public void setComponent(PipelineComponent component, Set allowed) { // showPrev = component.getPrevious() == null; // showNext = component.getNext() == null; // showMiddle = (component instanceof InlineComponent) && !component.getControlPoint().isFixed(); showPrev = allowed.contains(PositionType.PREVIOUS); showNext = allowed.contains(PositionType.NEXT); showMiddle = allowed.contains(PositionType.SPLIT); middle = component.getControlPoint().getWorldPosition(); component.getControlPoint().getControlPointEnds(prev, next); } private void loadData() { String middleTexFile = PluginTools.getAbsolutePath(Activator.getDefault().getBundle(), "icons/middle.png"); String plusTexFile = PluginTools.getAbsolutePath(Activator.getDefault().getBundle(), "icons/plus.png"); if (middleTexFile == null || plusTexFile == null) throw new RuntimeException("Cannot resolve required image files."); vtkPoints points = new vtkPoints(); points.InsertNextPoint(-8, -8, 0.0); points.InsertNextPoint( 8, -8, 0.0); points.InsertNextPoint( 8, 8, 0.0); points.InsertNextPoint(-8, 8, 0.0); vtkCellArray cellArray = new vtkCellArray(); vtkPolygon polygon = new vtkPolygon(); polygon.GetPointIds().SetNumberOfIds(4); polygon.GetPointIds().SetId(0, 0); polygon.GetPointIds().SetId(1, 1); polygon.GetPointIds().SetId(2, 2); polygon.GetPointIds().SetId(3, 3); cellArray.InsertNextCell(polygon); vtkPolyData quad = new vtkPolyData(); quad.SetPoints(points); quad.SetPolys(cellArray); vtkFloatArray texCoords = new vtkFloatArray(); texCoords.SetNumberOfComponents(2); texCoords.InsertNextTuple2(0.0, 0.0); texCoords.InsertNextTuple2(1.0, 0.0); texCoords.InsertNextTuple2(1.0, 1.0); texCoords.InsertNextTuple2(0.0, 1.0); quad.GetPointData().SetTCoords(texCoords); vtkPNGReader middleReader = new vtkPNGReader(); middleReader.SetFileName(middleTexFile); vtkPNGReader plusReader = new vtkPNGReader(); plusReader.SetFileName(plusTexFile); vtkTexture middleTex = new vtkTexture(); middleTex.SetInputConnection(middleReader.GetOutputPort()); middleTex.SetInterpolate(1); vtkTexture plusTex = new vtkTexture(); plusTex.SetInputConnection(plusReader.GetOutputPort()); plusTex.SetInterpolate(1); vtkPolyDataMapper2D mapper = new vtkPolyDataMapper2D(); mapper.SetInputData(quad); nextProp = new vtkTexturedActor2D(); prevProp = new vtkTexturedActor2D(); middleProp = new vtkTexturedActor2D(); nextProp.SetMapper(mapper); nextProp.SetTexture(plusTex); nextProp.SetPickable(1); prevProp.SetMapper(mapper); prevProp.SetTexture(plusTex); prevProp.SetPickable(1); middleProp.SetMapper(mapper); middleProp.SetTexture(middleTex); middleProp.SetPickable(1); plusReader.GetOutputPort().Delete(); plusReader.Delete(); middleReader.GetOutputPort().Delete(); middleReader.Delete(); middleTex.Delete(); plusTex.Delete(); mapper.Delete(); quad.GetPointData().Delete(); quad.Delete(); points.Delete(); polygon.GetPointIds().Delete(); polygon.Delete(); cellArray.Delete(); texCoords.Delete(); } public PositionType getPickedPosition(vtkProp[] picked) { if (picked == null) return null; for (vtkProp p : picked) { if (p.equals(middleProp)) return PositionType.SPLIT; if (p.equals(nextProp)) return PositionType.NEXT; if (p.equals(prevProp)) return PositionType.PREVIOUS; } return null; } }