/******************************************************************************* * Copyright (c) 2012, 2013 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.g3d.vtk.common; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.simantics.g3d.scenegraph.IG3DNode; import org.simantics.g3d.scenegraph.NodeHighlighter; import org.simantics.g3d.scenegraph.NodeHighlighter.HighlightEventType; import org.simantics.g3d.scenegraph.NodeHighlighter.HighlightObjectType; import org.simantics.g3d.scenegraph.base.INode; import org.simantics.g3d.tools.AdaptationUtils; import org.simantics.utils.threads.AWTThread; import org.simantics.utils.threads.ThreadUtils; import vtk.vtkActor; import vtk.vtkAlgorithm; import vtk.vtkAlgorithmOutput; import vtk.vtkFeatureEdges; import vtk.vtkMapper; import vtk.vtkProp; import vtk.vtkProperty; public class SelectionHighlighter implements ISelectionChangedListener { protected VtkView panel; protected VTKNodeMap nodeMap; protected List selectedNodes = new ArrayList(); protected List selectedActors = new ArrayList(); protected HighlightObjectType type = HighlightObjectType.Node; public SelectionHighlighter(VtkView panel, VTKNodeMap nodeMap) { this.panel = panel; this.nodeMap = nodeMap; } @Override public void selectionChanged(SelectionChangedEvent event) { final ISelection s = event.getSelection(); if (Thread.currentThread().equals(panel.getThreadQueue().getThread())) highlight(s); else { ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { @Override public void run() { highlight(s); //System.out.println(this.getClass().getName() + " highlight "); //panel.Render(); panel.refresh(); } }); } } protected void hilight(INode node, HighlightEventType type) { if (node instanceof NodeHighlighter) { ((NodeHighlighter)node).highlight(type); return; } if (type == HighlightEventType.Selection) { setSelectedColor(node); } else if (type == HighlightEventType.ClearSelection) { setDefaultColor(node); } } protected void hilight(vtkActor actor, HighlightEventType type) { if (type == HighlightEventType.Selection) { setColor(actor,false,new double[]{1,0,0}); setColor(actor,true,new double[]{1,0,1}); } else if (type == HighlightEventType.ClearSelection) { setColor(actor,false,new double[]{1,1,0}); setColor(actor,true,new double[]{0,0,0}); } } protected void highlight(ISelection s) { highlight(s, HighlightEventType.Selection, HighlightEventType.ClearSelection); } protected void highlight(ISelection s, HighlightEventType apply, HighlightEventType clear) { boolean changed = false; if (type == HighlightObjectType.Node) { Collection currentSelectedNodes = AdaptationUtils.adaptToCollection(s,IG3DNode.class);//getSelectedNodes(currentSelectedActors); if (currentSelectedNodes.size() == 0) { Collection currentSelectedActors = AdaptationUtils.adaptToCollection(s, vtkProp.class); currentSelectedNodes = getSelectedNodes(currentSelectedActors); } for (IG3DNode node : selectedNodes) { if (!currentSelectedNodes.contains(node)) { hilight((INode)node, clear); changed = true; } } for (IG3DNode node : currentSelectedNodes) { if (!selectedNodes.contains(node)) { hilight((INode)node, apply); changed = true; } } selectedNodes.clear(); selectedNodes.addAll(currentSelectedNodes); //selectedNodes = currentSelectedNodes; } else { Collection currentSelectedActors = AdaptationUtils.adaptToCollection(s, vtkActor.class); for (vtkActor act : selectedActors) { if (!currentSelectedActors.contains(act)) { hilight(act,clear); changed = true; } } for (vtkActor act : currentSelectedActors) { if (!selectedActors.contains(act)) { hilight(act,apply); changed = true; } } selectedActors.clear(); selectedActors.addAll(currentSelectedActors); } if (changed) { panel.refresh(); } } protected List getSelectedNodes(Collection selectedActors) { List currentSelectedNodes = new ArrayList(); for (vtkProp a : selectedActors) { INode node = nodeMap.getNode((vtkProp)a); if (node == null || !(node instanceof IG3DNode)) continue; if (!currentSelectedNodes.contains(node)) currentSelectedNodes.add((IG3DNode)node); } return currentSelectedNodes; } protected void setDefaultColor(INode node) { double color[] = new double[]{1,1,0}; setColor(node, false, color); } protected void setSelectedColor(INode node) { double color[] = new double[]{1,0,0}; setColor(node, false, color); } public void setColor(INode node, boolean edge, double color[]) { for (vtkProp prop : nodeMap.getRenderObjects(node)) { if (prop instanceof vtkActor) { vtkActor act = (vtkActor)prop; setColor(act, edge, color); } } } protected void setColor(vtkActor act, boolean edge, double color[]) { vtkMapper mapper = act.GetMapper(); vtkAlgorithmOutput out = mapper.GetInputConnection(0, 0); vtkAlgorithm producer = out.GetProducer(); boolean isEdge = (producer instanceof vtkFeatureEdges); producer.Delete(); if (isEdge == edge) { vtkProperty property = act.GetProperty(); property.SetColor(color); property.Delete(); } out.Delete(); mapper.Delete(); } }