]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/InteractiveVtkComposite.java
da984c086650c2c4578b7593175e44a4c5a9cfb1
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / swt / InteractiveVtkComposite.java
1 package org.simantics.g3d.vtk.swt;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.eclipse.core.runtime.Platform;
7 import org.eclipse.swt.widgets.Composite;
8 import org.simantics.g3d.scenegraph.RenderListener;
9 import org.simantics.g3d.vtk.action.vtkAction;
10 import org.simantics.g3d.vtk.common.VtkView;
11 import org.simantics.utils.threads.IThreadWorkQueue;
12 import org.simantics.utils.threads.SWTThread;
13 import org.simantics.utils.threads.ThreadUtils;
14
15 import vtk.vtkAbstractPicker;
16 import vtk.vtkActor2D;
17 import vtk.vtkActor2DCollection;
18 import vtk.vtkAreaPicker;
19 import vtk.vtkAssemblyNode;
20 import vtk.vtkAssemblyPath;
21 import vtk.vtkCellPicker;
22 import vtk.vtkObject;
23 import vtk.vtkObjectBase;
24 import vtk.vtkPointPicker;
25 import vtk.vtkProp;
26 import vtk.vtkProp3DCollection;
27 import vtk.vtkPropCollection;
28 import vtk.vtkPropPicker;
29 import vtk.vtkRenderWindow;
30 import vtk.vtkRenderer;
31 import vtk.vtkScenePicker;
32 import vtk.rendering.swt.vtkSwtComponent;
33
34 public class InteractiveVtkComposite extends vtkSwtComponent implements VtkView{
35         
36         Composite parentComposite;
37         public InteractiveVtkComposite(Composite parentComposite) {
38                 super(parentComposite);
39                 this.parentComposite = parentComposite;
40
41                 if (!Platform.inDevelopmentMode()) {
42                         // This is actually a static method in C++
43                         new vtkObject().GlobalWarningDisplayOff();
44                 }
45         }
46         
47         private boolean updating = false;
48         private Object mutex = new Object();
49         
50         @Override
51         public void refresh() {
52 //              if (Thread.currentThread() == getThreadQueue().getThread())
53 //                      update();
54 //              else {
55                         synchronized (mutex) {
56                                 if (!updating) {
57                                         updating = true;
58                                         ThreadUtils.asyncExec(getThreadQueue(), new Runnable() {
59                                                 
60                                                 @Override
61                                                 public void run() {
62                                                         if (parentComposite.isDisposed())
63                                                                 return;
64                                                         synchronized (mutex) {
65                                                                 updating = false;
66                                                         }
67                                                         update();
68                                                 }
69                                         });
70                                         
71                                 }
72                         }
73 //              }
74         }
75         
76         boolean update = false;
77         @Override
78         public void update() {
79                 if (update)
80                         return;
81                 update = true;
82                 super.update();
83                 update = false;
84         }
85         
86         @Override
87         public IThreadWorkQueue getThreadQueue() {
88                 return SWTThread.getThreadAccess();
89         }
90         
91
92         boolean render = false;
93         @Override
94         public void Render() {
95                 if (render)
96                         return;
97 //              System.out.println(getClass().getSimpleName() +" render");
98                 render = true;
99                 firePreRender();
100                 super.Render();
101                 firePostRender();
102                 render = false;
103         }
104
105         public void addListener(RenderListener l) {
106                 listeners.add(l);
107         }
108         
109         public void removeListener(RenderListener l) {
110                 listeners.remove(l);
111         }
112         
113         private List<RenderListener> listeners = new ArrayList<RenderListener>();
114         
115         List<RenderListener> list = new ArrayList<RenderListener>();
116         
117         private void firePreRender() {
118                 if (listeners.size() > 0) {
119                         list.addAll(listeners);
120                         for (RenderListener l : list)
121                                 l.preRender();
122                         list.clear();
123                 }
124         }
125         
126         private void firePostRender() {
127                 if (listeners.size() > 0) {
128                         list.addAll(listeners);
129                         for (RenderListener l : list)
130                                 l.postRender();
131                         list.clear();
132                 }
133         }
134
135         
136         private List<vtkObjectBase> deletable = new ArrayList<vtkObjectBase>();
137         
138         public void addDeletable(vtkObjectBase o) {
139                 deletable.add(o);
140         }
141         
142         public void removeDeletable (vtkObjectBase o) {
143                 deletable.remove(o);
144         }
145         
146         @Override
147         public void Delete() {
148                 for (vtkObjectBase o : deletable) {
149                         if (o.GetVTKId() != 0) {
150                                 o.Delete();
151                         }
152                 }
153                 deletable.clear();
154                 
155                 super.Delete();
156         }
157         
158         private vtkSwtAction defaultAction;
159         private vtkSwtAction currentAction;
160         
161         public void setActiveAction(vtkAction action) {
162                 if (action.equals(currentAction))
163                         return;
164                 if (currentAction != null)
165                         currentAction.deattach();
166                 currentAction = (vtkSwtAction)action;
167                 if (action != null)
168                         action.attach();
169         }
170         
171         public void setDefaultAction(vtkAction defaultAction) {
172                 this.defaultAction = (vtkSwtAction)defaultAction;
173         }
174         
175         public void useDefaultAction() {
176                 setActiveAction(defaultAction);
177         }
178         
179         public vtkAction getDefaultAction() {
180                 return defaultAction;
181         }
182         
183         public void lock() {
184                 getVTKLock().lock();
185         }
186         
187         public void unlock() {
188                 getVTKLock().unlock();
189         }
190         
191         private vtkScenePicker scenePicker;
192         
193         int pickType = 4;
194         
195         public int getPickType() {
196                 return pickType;
197         }
198         
199         public void setPickType(int pickType) {
200                 this.pickType = pickType;
201         }
202         
203         public vtkProp[] pick(int x, int y) {
204                 
205                 
206                 vtkRenderWindow rw = getRenderWindow();
207                 vtkRenderer ren = getRenderer();
208                 
209                 int ax = x;
210                 int ay = rw.GetSize()[1] - y;
211
212                 if (pickType == 0) {
213                         throw new IllegalStateException("SWT Binding does not work with hw picking");
214 //                      lock();
215 //                      ren.BreakOnError();
216 //                      ren.DrawOff();
217 //                      vtkPropPicker picker = new vtkPropPicker();
218 //                      picker.DebugOn();
219 //                      //picker.PickProp(x, rw.GetSize()[1] - y, ren);
220 //                      picker.Pick(x, rw.GetSize()[1] - y,0, ren);
221 //                      ren.DrawOn();
222 //                      unlock();
223 //      
224 //                      vtkAssemblyPath apath = picker.GetPath();
225 //                      return processPick(picker, apath);
226 //                      
227                 } else if (pickType == 1) {
228                         throw new IllegalStateException("SWT Binding does not work with hw picking");
229 //                      if (scenePicker == null) {
230 //                              scenePicker = new vtkScenePicker();
231 //                              scenePicker.SetRenderer(ren);
232 //                              scenePicker.EnableVertexPickingOn();
233 //                              
234 //                      }
235 //                      lock();
236 //
237 //                      vtkAssemblyPath apath = ren.PickProp(ax, ay);
238 //                      
239 //                      unlock();
240 //                      
241 //                      if (apath != null) {
242 //                              apath.InitTraversal();
243 //                              vtkAssemblyNode node = apath.GetLastNode();
244 //                              vtkProp test = (vtkProp) node.GetViewProp();
245 //                              apath.Delete();
246 //                              node.Delete();
247 //                              return new vtkProp[]{test};
248 //      
249 //                      }
250                         
251                 } else if (pickType == 2) {
252                         vtkPointPicker picker = new vtkPointPicker();
253                         //picker.SetTolerance(2.0/(double)rw.GetSize()[0]);
254                         picker.SetTolerance(0.00001);
255                         lock();
256                         picker.Pick(new double[]{ax, ay,0}, ren);
257                         unlock();
258                         
259                         vtkAssemblyPath apath = picker.GetPath();
260                         return processPick(picker, apath);
261                 } else if (pickType == 3) {
262                         vtkAreaPicker picker = new vtkAreaPicker();
263                         lock();
264                         picker.Pick(new double[]{ax, ay,0}, ren);
265                         unlock();
266                         vtkAssemblyPath apath = picker.GetPath();
267                         return processPick(picker, apath);
268                 } else if (pickType == 4) {
269                         vtkCellPicker picker = new vtkCellPicker();
270                         picker.SetTolerance(0.00001);
271                         lock();
272                         picker.Pick(new double[]{ax, ay,0}, ren);
273                         unlock();       
274                         vtkAssemblyPath apath = picker.GetPath();
275                         return processPick(picker, apath);
276                 } else if (pickType == 5) {
277                         vtkActor2DCollection coll = ren.GetActors2D(); 
278                         coll.InitTraversal();
279                         vtkActor2D a;
280                         
281                         List<vtkActor2D> picked = new ArrayList<vtkActor2D>();
282                         while ((a = coll.GetNextItem()) != null) {
283                                 double pos[] = a.GetPosition();
284                                 // TODO : width and height do not seem to affect the perceived size of Actor2D.
285                                 //        actual size should be fetched from mapper. 
286                                 double w = a.GetWidth();
287                                 double h = a.GetHeight();
288                                 int minx = (int)(pos[0]-w*0.5);
289                                 int miny = (int)(pos[1]-h*0.5);
290                                 int maxx = (int)(pos[0]+w*0.5);
291                                 int maxy = (int)(pos[1]+h*0.5);
292                                 if (minx <= ax && maxx >= ax &&
293                                         miny <= ay && maxy >= ay) {
294                                         picked.add(a);
295                                 }
296                         }
297                         return picked.toArray(new vtkProp[picked.size()]);
298                 }
299
300                 return null;
301         }
302         
303         public vtkProp[] pick2(int x, int y) {
304                 vtkRenderWindow rw = getRenderWindow();
305                 vtkRenderer ren = getRenderer();
306                 
307 //              vtkPicker picker = new vtkPicker();
308 //              vtkAbstractPicker picker = new vtkAbstractPicker();
309 //              picker.Pick(x, rw.GetSize()[1] - y, ren);
310 //              // see page 60 of VTK user's guide
311 //
312                 if (pickType == 0) {
313         
314                         vtkPropPicker picker = new vtkPropPicker();
315                         lock();
316                         picker.PickProp(x, rw.GetSize()[1] - y, ren);
317         
318                         unlock();
319                         vtkPropCollection coll = picker.GetPickList();
320                         return processPick(picker, coll);
321                         
322                 } else if (pickType == 1) {
323                         if (scenePicker == null) {
324                                 scenePicker = new vtkScenePicker();
325                                 scenePicker.SetRenderer(ren);
326                                 scenePicker.EnableVertexPickingOn();
327                                 scenePicker.DebugOn();
328                                 
329                         }
330                         lock();
331
332                         
333                         vtkAssemblyPath apath = ren.PickProp(x, rw.GetSize()[1] - y);
334                         
335                         unlock();
336                         
337                         if (apath != null) {
338                                 apath.InitTraversal();
339
340                                 
341                                 vtkAssemblyNode node = apath.GetLastNode();
342                                 vtkProp test = (vtkProp) node.GetViewProp();
343                                 apath.Delete();
344                                 node.Delete();
345                                 return new vtkProp[]{test};
346         
347                         }
348                         
349                 } else if (pickType == 2) {
350                         vtkPointPicker picker = new vtkPointPicker();
351                         picker.SetTolerance(2.0/(double)rw.GetSize()[0]);
352                         lock();
353                         picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);
354                         unlock();
355                         vtkProp3DCollection coll = picker.GetProp3Ds();
356                         return processPick(picker, coll);
357                 } else if (pickType == 3) {
358                         vtkAreaPicker picker = new vtkAreaPicker();
359                         lock();
360                         picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);
361                         //picker.AreaPick(x-1, rw.GetSize()[1] - y-1,x+1,rw.GetSize()[1] - y+1, ren);
362                         unlock();
363                         vtkProp3DCollection coll = picker.GetProp3Ds();
364                         return processPick(picker, coll);
365                 } else if (pickType == 4) {
366                         vtkCellPicker picker = new vtkCellPicker();
367                         picker.SetTolerance(2.0/(double)rw.GetSize()[0]);
368                         lock();
369                         picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);
370                         unlock();       
371                         vtkProp3DCollection coll = picker.GetProp3Ds();
372                         return processPick(picker, coll);
373                 }
374
375                 return null;
376         }
377         
378         private vtkProp[] processPick(vtkAbstractPicker picker, vtkAssemblyPath apath) {
379 //              double[] pickPos = picker.GetPickPosition();
380                 picker.Delete();
381                 if (apath != null) {
382                         apath.InitTraversal();
383                         vtkProp result[] = new vtkProp[apath.GetNumberOfItems()];
384                         for (int i = apath.GetNumberOfItems()-1; i >= 0; i--) {
385                                 vtkAssemblyNode node = apath.GetNextNode();
386                                 vtkProp test = (vtkProp) node.GetViewProp();
387 //                              System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId());
388                                 result[i] = test;
389                                 node.Delete();
390                         }
391                         apath.Delete();
392                         return result;
393
394                 }
395                 return null;
396         }
397         
398         private vtkProp[] processPick(vtkAbstractPicker picker, vtkPropCollection coll) {
399 //              double[] pickPos = picker.GetPickPosition();
400                 picker.Delete();
401                 if (coll != null) {
402                         coll.InitTraversal();
403                         vtkProp result[] = new vtkProp[coll.GetNumberOfItems()];
404                         for (int i = coll.GetNumberOfItems()-1; i >= 0; i--) {
405                                 vtkProp test = coll.GetNextProp();
406                                 
407 //                              System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId());
408                                 result[i] = test;
409                                 
410                         }
411                         coll.Delete();
412                         return result;
413
414                 }
415                 return null;
416         }
417         
418         
419         
420 }