package org.simantics.g3d.vtk.swt; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.widgets.Composite; import org.simantics.g3d.scenegraph.RenderListener; import org.simantics.g3d.vtk.action.vtkAction; import org.simantics.g3d.vtk.common.VtkView; import org.simantics.utils.threads.IThreadWorkQueue; import org.simantics.utils.threads.SWTThread; import org.simantics.utils.threads.ThreadUtils; import vtk.vtkAbstractPicker; import vtk.vtkActor2D; import vtk.vtkActor2DCollection; import vtk.vtkAreaPicker; import vtk.vtkAssemblyNode; import vtk.vtkAssemblyPath; import vtk.vtkCellPicker; import vtk.vtkObject; import vtk.vtkObjectBase; import vtk.vtkPointPicker; import vtk.vtkProp; import vtk.vtkProp3DCollection; import vtk.vtkPropCollection; import vtk.vtkPropPicker; import vtk.vtkRenderWindow; import vtk.vtkRenderer; import vtk.vtkScenePicker; import vtk.rendering.swt.vtkSwtComponent; public class InteractiveVtkComposite extends vtkSwtComponent implements VtkView{ Composite parentComposite; public InteractiveVtkComposite(Composite parentComposite) { super(parentComposite); this.parentComposite = parentComposite; // This is actually a static method in C++ new vtkObject().GlobalWarningDisplayOff(); } private boolean updating = false; private Object mutex = new Object(); @Override public void refresh() { // if (Thread.currentThread() == getThreadQueue().getThread()) // update(); // else { synchronized (mutex) { if (!updating) { updating = true; ThreadUtils.asyncExec(getThreadQueue(), new Runnable() { @Override public void run() { if (parentComposite.isDisposed()) return; synchronized (mutex) { updating = false; } update(); } }); } } // } } boolean update = false; @Override public void update() { if (update) return; update = true; super.update(); update = false; } @Override public IThreadWorkQueue getThreadQueue() { return SWTThread.getThreadAccess(); } boolean render = false; @Override public void Render() { if (render) return; // System.out.println(getClass().getSimpleName() +" render"); render = true; firePreRender(); super.Render(); firePostRender(); render = false; } public void addListener(RenderListener l) { listeners.add(l); } public void removeListener(RenderListener l) { listeners.remove(l); } private List listeners = new ArrayList(); List list = new ArrayList(); private void firePreRender() { if (listeners.size() > 0) { list.addAll(listeners); for (RenderListener l : list) l.preRender(); list.clear(); } } private void firePostRender() { if (listeners.size() > 0) { list.addAll(listeners); for (RenderListener l : list) l.postRender(); list.clear(); } } private List deletable = new ArrayList(); public void addDeletable(vtkObjectBase o) { deletable.add(o); } public void removeDeletable (vtkObjectBase o) { deletable.remove(o); } @Override public void Delete() { for (vtkObjectBase o : deletable) { if (o.GetVTKId() != 0) { o.Delete(); } } deletable.clear(); super.Delete(); } private vtkSwtAction defaultAction; private vtkSwtAction currentAction; public void setActiveAction(vtkAction action) { if (action.equals(currentAction)) return; if (currentAction != null) currentAction.deattach(); currentAction = (vtkSwtAction)action; if (action != null) action.attach(); } public void setDefaultAction(vtkAction defaultAction) { this.defaultAction = (vtkSwtAction)defaultAction; } public void useDefaultAction() { setActiveAction(defaultAction); } public vtkAction getDefaultAction() { return defaultAction; } public void lock() { getVTKLock().lock(); } public void unlock() { getVTKLock().unlock(); } private vtkScenePicker scenePicker; int pickType = 4; public int getPickType() { return pickType; } public void setPickType(int pickType) { this.pickType = pickType; } public vtkProp[] pick(int x, int y) { vtkRenderWindow rw = getRenderWindow(); vtkRenderer ren = getRenderer(); int ax = x; int ay = rw.GetSize()[1] - y; if (pickType == 0) { throw new IllegalStateException("SWT Binding does not work with hw picking"); // lock(); // ren.BreakOnError(); // ren.DrawOff(); // vtkPropPicker picker = new vtkPropPicker(); // picker.DebugOn(); // //picker.PickProp(x, rw.GetSize()[1] - y, ren); // picker.Pick(x, rw.GetSize()[1] - y,0, ren); // ren.DrawOn(); // unlock(); // // vtkAssemblyPath apath = picker.GetPath(); // return processPick(picker, apath); // } else if (pickType == 1) { throw new IllegalStateException("SWT Binding does not work with hw picking"); // if (scenePicker == null) { // scenePicker = new vtkScenePicker(); // scenePicker.SetRenderer(ren); // scenePicker.EnableVertexPickingOn(); // // } // lock(); // // vtkAssemblyPath apath = ren.PickProp(ax, ay); // // unlock(); // // if (apath != null) { // apath.InitTraversal(); // vtkAssemblyNode node = apath.GetLastNode(); // vtkProp test = (vtkProp) node.GetViewProp(); // apath.Delete(); // node.Delete(); // return new vtkProp[]{test}; // // } } else if (pickType == 2) { vtkPointPicker picker = new vtkPointPicker(); //picker.SetTolerance(2.0/(double)rw.GetSize()[0]); picker.SetTolerance(0.00001); lock(); picker.Pick(new double[]{ax, ay,0}, ren); unlock(); vtkAssemblyPath apath = picker.GetPath(); return processPick(picker, apath); } else if (pickType == 3) { vtkAreaPicker picker = new vtkAreaPicker(); lock(); picker.Pick(new double[]{ax, ay,0}, ren); unlock(); vtkAssemblyPath apath = picker.GetPath(); return processPick(picker, apath); } else if (pickType == 4) { vtkCellPicker picker = new vtkCellPicker(); picker.SetTolerance(0.00001); lock(); picker.Pick(new double[]{ax, ay,0}, ren); unlock(); vtkAssemblyPath apath = picker.GetPath(); return processPick(picker, apath); } else if (pickType == 5) { vtkActor2DCollection coll = ren.GetActors2D(); coll.InitTraversal(); vtkActor2D a; List picked = new ArrayList(); while ((a = coll.GetNextItem()) != null) { double pos[] = a.GetPosition(); // TODO : width and height do not seem to affect the perceived size of Actor2D. // actual size should be fetched from mapper. double w = a.GetWidth(); double h = a.GetHeight(); int minx = (int)(pos[0]-w*0.5); int miny = (int)(pos[1]-h*0.5); int maxx = (int)(pos[0]+w*0.5); int maxy = (int)(pos[1]+h*0.5); if (minx <= ax && maxx >= ax && miny <= ay && maxy >= ay) { picked.add(a); } } return picked.toArray(new vtkProp[picked.size()]); } return null; } public vtkProp[] pick2(int x, int y) { vtkRenderWindow rw = getRenderWindow(); vtkRenderer ren = getRenderer(); // vtkPicker picker = new vtkPicker(); // vtkAbstractPicker picker = new vtkAbstractPicker(); // picker.Pick(x, rw.GetSize()[1] - y, ren); // // see page 60 of VTK user's guide // if (pickType == 0) { vtkPropPicker picker = new vtkPropPicker(); lock(); picker.PickProp(x, rw.GetSize()[1] - y, ren); unlock(); vtkPropCollection coll = picker.GetPickList(); return processPick(picker, coll); } else if (pickType == 1) { if (scenePicker == null) { scenePicker = new vtkScenePicker(); scenePicker.SetRenderer(ren); scenePicker.EnableVertexPickingOn(); scenePicker.DebugOn(); } lock(); vtkAssemblyPath apath = ren.PickProp(x, rw.GetSize()[1] - y); unlock(); if (apath != null) { apath.InitTraversal(); vtkAssemblyNode node = apath.GetLastNode(); vtkProp test = (vtkProp) node.GetViewProp(); apath.Delete(); node.Delete(); return new vtkProp[]{test}; } } else if (pickType == 2) { vtkPointPicker picker = new vtkPointPicker(); picker.SetTolerance(2.0/(double)rw.GetSize()[0]); lock(); picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren); unlock(); vtkProp3DCollection coll = picker.GetProp3Ds(); return processPick(picker, coll); } else if (pickType == 3) { vtkAreaPicker picker = new vtkAreaPicker(); lock(); picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren); //picker.AreaPick(x-1, rw.GetSize()[1] - y-1,x+1,rw.GetSize()[1] - y+1, ren); unlock(); vtkProp3DCollection coll = picker.GetProp3Ds(); return processPick(picker, coll); } else if (pickType == 4) { vtkCellPicker picker = new vtkCellPicker(); picker.SetTolerance(2.0/(double)rw.GetSize()[0]); lock(); picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren); unlock(); vtkProp3DCollection coll = picker.GetProp3Ds(); return processPick(picker, coll); } return null; } private vtkProp[] processPick(vtkAbstractPicker picker, vtkAssemblyPath apath) { // double[] pickPos = picker.GetPickPosition(); picker.Delete(); if (apath != null) { apath.InitTraversal(); vtkProp result[] = new vtkProp[apath.GetNumberOfItems()]; for (int i = apath.GetNumberOfItems()-1; i >= 0; i--) { vtkAssemblyNode node = apath.GetNextNode(); vtkProp test = (vtkProp) node.GetViewProp(); // System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId()); result[i] = test; node.Delete(); } apath.Delete(); return result; } return null; } private vtkProp[] processPick(vtkAbstractPicker picker, vtkPropCollection coll) { // double[] pickPos = picker.GetPickPosition(); picker.Delete(); if (coll != null) { coll.InitTraversal(); vtkProp result[] = new vtkProp[coll.GetNumberOfItems()]; for (int i = coll.GetNumberOfItems()-1; i >= 0; i--) { vtkProp test = coll.GetNextProp(); // System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId()); result[i] = test; } coll.Delete(); return result; } return null; } }