/******************************************************************************* * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. * 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 fi.vtt.simantics.processeditor.monitors; import java.net.URL; import java.util.ArrayList; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.swt.graphics.Rectangle; import org.simantics.db.Graph; import org.simantics.proconf.g3d.base.G3DTools; import org.simantics.proconf.g3d.base.MathTools; import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; import org.simantics.proconf.g3d.base.VecmathJmeTools; import org.simantics.proconf.g3d.scenegraph.IGraphicsNode; import org.simantics.proconf.g3d.stubs.G3DNode; import com.jme.image.Texture; import com.jme.math.Vector2f; import com.jme.math.Vector3f; import com.jme.renderer.ColorRGBA; import com.jme.renderer.Renderer; import com.jme.scene.Node; import com.jme.scene.Text; import com.jme.scene.shape.Quad; import com.jme.scene.state.AlphaState; import com.jme.scene.state.MaterialState; import com.jme.scene.state.RenderState; import com.jme.scene.state.TextureState; import com.jme.util.TextureManager; import fi.vtt.simantics.processeditor.ProcessResource; import fi.vtt.simantics.processeditor.stubs.InlineComponent; /** * A monitor implemetation that uses JME's text component to show it's information. * * @author Marko Luukkainen * */ public class TextMonitor implements Monitor { private enum Type{POSITION,PIPE}; private Type type; public static String fontLocation = "data/textures/tahoma512.png"; private ThreeDimensionalEditorBase editor; private ArrayList texts = new ArrayList(); private Node monitorNode = new Node(""); Node textNode; private IGraphicsNode node = null; Point3d start; Point3d end; Point3d middle; float width = 0.f; float height = 0.f; float textHeight = 0.f; Quad background; private MonitorTextProvider provider = new ObjectPropertyProvider(); public TextMonitor(ThreeDimensionalEditorBase editor) { this.editor = editor; textNode = new Node(""); AlphaState as1 = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState(); as1.setBlendEnabled(true); as1.setSrcFunction(AlphaState.SB_SRC_ALPHA); as1.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); as1.setTestEnabled(true); as1.setTestFunction(AlphaState.TF_GREATER); as1.setEnabled(true); MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState(); ms.setEmissive(new ColorRGBA(0.f,1.f,0.f,0.f)); TextureState font = editor.getRenderingComponent().getDisplaySystem().getRenderer().createTextureState(); /** The texture is loaded from fontLocation */ font.setTexture(loadFontTexture()); font.setEnabled(true); textNode.setRenderState(font); textNode.setRenderState(as1); textNode.setRenderState(ms); background = new Quad("",100.f,100.f); MaterialState ms2 = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState(); ms2.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.8f)); ms2.setDiffuse(new ColorRGBA(0.f,0.f,0.f,0.8f)); AlphaState as2 = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState(); as2.setBlendEnabled(true); as2.setSrcFunction(AlphaState.SB_SRC_ALPHA); as2.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); as2.setTestEnabled(true); as2.setTestFunction(AlphaState.TF_GREATER); as2.setEnabled(true); monitorNode.setRenderState(ms2); monitorNode.setRenderState(as2); background.setRenderQueueMode(Renderer.QUEUE_ORTHO); textNode.setRenderQueueMode(Renderer.QUEUE_ORTHO); monitorNode.attachChild(background); monitorNode.attachChild(textNode); // editor.getRenderingComponent().getOrthoNode().attachChild(monitorNode); } public boolean acceptNode(Graph graph,IGraphicsNode node) { G3DNode n = node.getG3DNode(graph); if (this.node == null || !node.equals(this.node)) { if (n.getLocalPosition() != null) { return true; } else if (n.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthInlineComponent)) { return true; } } return false; } public void setNode(Graph graph, IGraphicsNode node) { G3DNode n = node.getG3DNode(graph); if (n.getLocalPosition() != null) { type = Type.POSITION; } else if (n.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthInlineComponent)) { type = Type.PIPE; InlineComponent ic = new InlineComponent(n); start = G3DTools.getPoint(ic.getControlPoint().getPrevious().getWorldPosition()); end = G3DTools.getPoint(ic.getControlPoint().getNext().getWorldPosition()); Vector3d dir = new Vector3d(end); dir.sub(start); dir.scale(0.5); middle = new Point3d(start); middle.add(dir); } else { return; } this.node = node; provider.setSource(n); ArrayList titles = provider.getTexts(graph); for (int i = titles.size() - 1; i < texts.size(); i++) { texts.get(i).removeFromParent(); } while (texts.size() < titles.size()) { Text text = new Text("", ""); texts.add(text); textNode.attachChild(text); } width = 0.f; height = 0.f; for (int i = 0; i < titles.size(); i++) { Text text = texts.get(i); text.print(titles.get(i)); width = Math.max(width,text.getWidth()); textHeight = text.getHeight(); height += textHeight; textNode.attachChild(text); } background.resize(width+20.f, height+10.f); if (monitorNode.getParent() == null) editor.getScenegraphAdapter().getRoot().attachChild(monitorNode); } private void updateText(Graph graph) { ArrayList titles = provider.getTexts(graph); float newWidth = 0.f; for (int i = 0; i < titles.size(); i++) { Text text = texts.get(i); text.print(titles.get(i)); newWidth = Math.max(newWidth,text.getWidth()); } if (newWidth != width) { width = newWidth; background.resize(width+20.f, height+10.f); } } public void update() { if (node == null) return; Vector2f v; if (type == Type.POSITION) { v = editor.getScreenCoord(VecmathJmeTools.getD(node.getGroup().getWorldTranslation())); } else { float mx = editor.getRenderingComponent().getDisplaySystem().getWidth(); float my = editor.getRenderingComponent().getDisplaySystem().getHeight(); Vector2f s = editor.getScreenCoord(start); Vector2f e = editor.getScreenCoord(end); Vector2f rs = new Vector2f(); Vector2f re = new Vector2f(); boolean in = MathTools.clipLineRectangle(s, e, new Vector2f(0.f,0.f), new Vector2f(mx,my), rs, re); if (in) { re.subtractLocal(rs); re.multLocal(0.5f); rs.addLocal(re); v = rs; } else { // just a hack to move monitor out of the view v = new Vector2f (mx+width,my+height); } } background.setLocalTranslation(new Vector3f(v.x,v.y,0.f)); float y = v.y + (height * 0.5f) - textHeight; v.x -= width * 0.5f; for (Text text : texts) { text.setLocalTranslation(new Vector3f(v.x,y,0.f)); y -= textHeight; } } @Override public void update(Graph graph) { updateText(graph); update(); } public IGraphicsNode getNode() { return node; } public void remove() { monitorNode.removeFromParent(); node = null; } protected Texture loadFontTexture() { URL url = FileLocator.find(com.jme.eclipse.Activator.getDefault().getBundle(),new Path(fontLocation),null); return TextureManager.loadTexture(url, Texture.MM_LINEAR, Texture.FM_LINEAR); } public void setTextProvider(MonitorTextProvider provider) { this.provider = provider; } }