package fi.vtt.simantics.processeditor.gizmo; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.vecmath.Point3d; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; import org.simantics.proconf.g3d.base.VecmathJmeTools; import org.simantics.proconf.g3d.gizmo.Gizmo; import org.simantics.utils.datastructures.Pair; import com.jme.bounding.BoundingSphere; import com.jme.image.Image; import com.jme.image.Texture; import com.jme.math.Vector3f; import com.jme.renderer.Renderer; import com.jme.scene.BillboardNode; import com.jme.scene.Node; import com.jme.scene.shape.Quad; import com.jme.scene.state.AlphaState; import com.jme.scene.state.LightState; import com.jme.scene.state.TextureState; import com.jme.scene.state.ZBufferState; import com.jme.util.TextureManager; import fi.vtt.simantics.processeditor.Activator; import fi.vtt.simantics.processeditor.actions.PositionType; /** * Gizmo that allows user to selected insertion point of a component * TODO : for splits we want use line between component ends to * position the button, instead of its center point. * * @author Marko Luukkainen * */ public class PositionSelectionGizmo implements Gizmo { private static String PICK_PREFIX = "insert"; private static String SPLIT_TEXTURE = "icons/middle.png"; private static String END_TEXTURE = "icons/plus.png"; private static String PORT_TEXTURE = END_TEXTURE; private ThreeDimensionalEditorBase parent; private boolean changed = false; private int selected = -1; private boolean useDistanceResize = true; private List nodes; private List alphaStates; private Node rootNode; public PositionSelectionGizmo(ThreeDimensionalEditorBase parent, List> positions) { this.parent = parent; rootNode = new Node(); rootNode.setCullMode(Node.CULL_NEVER); rootNode.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); rootNode.setLightCombineMode(LightState.OFF); int i = 0; nodes = new ArrayList(); alphaStates = new ArrayList(); // create a button (billboard) for each insertion position ZBufferState zs = parent.getRenderingComponent().getDisplaySystem().getRenderer().createZBufferState(); zs.setFunction(ZBufferState.CF_ALWAYS); for (Pair p : positions) { BillboardNode node = new BillboardNode(""); nodes.add(node); Quad quad = new Quad(PICK_PREFIX + i,1.f,1.f); TextureState ts = parent.getRenderingComponent().getDisplaySystem().getRenderer().createTextureState(); String filename = ""; switch (p.second) { case NEXT: case PREVIOUS: filename = END_TEXTURE; break; case SPLIT: filename = SPLIT_TEXTURE; break; case PORT: filename = PORT_TEXTURE; } URL url = FileLocator.find(Activator.getDefault().getBundle(), new Path(filename),null); Image image = TextureManager.loadImage(url, true); Texture texture = new Texture(); texture.setImage(image); texture.setFilter(Texture.FM_LINEAR); ts.setTexture(texture); quad.setRenderState(ts); AlphaState as = parent.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState(); as.setSrcFunction(AlphaState.SB_SRC_ALPHA); as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); as.setBlendEnabled(true); alphaStates.add(as); quad.setRenderState(as); quad.setRenderState(zs); node.attachChild(quad); node.setLocalTranslation(VecmathJmeTools.get(p.first)); quad.setModelBound(new BoundingSphere(0.5f,new Vector3f())); quad.updateModelBound(); rootNode.attachChild(node); i++; } } @Override public Node getNode() { return rootNode; } @Override public String getPickPrefix() { return PICK_PREFIX; } @Override public boolean isChanged() { return changed; } @Override public void setChanged(boolean b) { changed = b; } @Override public void setSelected(String name) { if (name == null) { setSelected(-1); return; } assert(name.startsWith(PICK_PREFIX)); setSelected(Integer.parseInt(name.substring(PICK_PREFIX.length()))); } private void setSelected(int i) { if (selected == i) return; if (selected != -1) { alphaStates.get(selected).setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); nodes.get(selected).getChild(0).setRenderState(alphaStates.get(selected)); } selected = i; if (selected != -1) { alphaStates.get(selected).setDstFunction(AlphaState.DB_ONE); nodes.get(selected).getChild(0).setRenderState(alphaStates.get(selected)); } parent.setViewChanged(true); } public int getSelected() { return selected; } public void update() { if (useDistanceResize) { Vector3f v = VecmathJmeTools.get(parent.getCamera().getCameraPos()); for (BillboardNode n : nodes) { float length = v.subtract(n.getWorldTranslation()).length(); n.setLocalScale(length * 0.06f); } } } }