/******************************************************************************* * 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.awt.Color; import java.util.ArrayList; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import org.simantics.db.Graph; import org.simantics.proconf.g3d.base.G3DTools; 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.Vector3f; import com.jme.renderer.ColorRGBA; 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.MaterialState; import com.jme.scene.state.RenderState; import com.jme.scene.state.TextureState; import com.jme.scene.state.ZBufferState; import com.jmex.awt.swingui.ImageGraphics; import fi.vtt.simantics.processeditor.ProcessResource; import fi.vtt.simantics.processeditor.stubs.InlineComponent; /** * A monitor that uses billboard to show it's information. * * @author Marko Luukkainen * */ //TODO : should it be variable length / fixed length inline component instead of Straight public class BillboardMonitor implements Monitor{ private enum Type{POSITION,PIPE}; private Type type; private ThreeDimensionalEditorBase editor; private BillboardNode monitorNode = null; private int monitorSize = 128; private ImageGraphics graphics = ImageGraphics.createInstance(monitorSize, monitorSize, 0); private Node currentParent = null; private IGraphicsNode node = null; private boolean useDistanceResize = true; Point3d start; Point3d end; Point3d middle; private MonitorTextProvider provider = new ObjectPropertyProvider(); public BillboardMonitor(ThreeDimensionalEditorBase editor) { this.editor = editor; monitorNode = new BillboardNode(""); monitorNode.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); ZBufferState zs = editor.getRenderingComponent() .getDisplaySystem().getRenderer().createZBufferState(); zs.setEnabled(true); zs.setFunction(ZBufferState.CF_ALWAYS); monitorNode.setRenderState(zs); Quad quad = new Quad(""); quad.initialize(3.f, 3.f); monitorNode.attachChild(quad); // SWTImageGraphics graphics = // SWTImageGraphics.createInstance(64,64, 0); graphics.clearRect(0, 0, monitorSize, monitorSize); // graphics.setFont(new Font("Arial",Font.PLAIN,30)); // graphics.setColor(Display.getDefault().getSystemColor(SWT.COLOR_GREEN)); graphics.setColor(new Color(0, 255, 0, 255)); graphics.drawString("Monitor", 0, 32); TextureState ts = editor.getRenderingComponent().getDisplaySystem().getRenderer().createTextureState(); Texture texture = new Texture(); texture.setApply(Texture.AM_MODULATE); // texture.setBlendColor(new ColorRGBA(1, 1, 1, 1)); texture.setFilter(Texture.MM_LINEAR); texture.setMipmapState(Texture.FM_LINEAR); texture.setImage(graphics.getImage()); graphics.update(); AlphaState as = editor.getRenderingComponent().getDisplaySystem() .getRenderer().createAlphaState(); as.setBlendEnabled(true); as.setSrcFunction(AlphaState.SB_SRC_ALPHA); as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); as.setTestEnabled(true); as.setTestFunction(AlphaState.TF_GREATER); ts.setTexture(texture); MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState(); ms.setEmissive(new ColorRGBA(1.f, 1.f, 1.f, 0.f)); monitorNode.setRenderState(ts); monitorNode.setRenderState(as); monitorNode.setRenderState(ms); graphics.drawLine(0, 33, monitorSize-1, 33); graphics.update(); } public boolean acceptNode(Graph graph, IGraphicsNode node) { Node selectedParent = node.getGroup(); if (currentParent == null || !selectedParent.equals(currentParent)) { if (node.getG3DNode(graph).getLocalPosition() != null) { return true; } else if (node.getG3DNode(graph).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; monitorNode.setLocalTranslation(new Vector3f(0.f,0.f,0.f)); } else if (n.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthInlineComponent)) { type = Type.PIPE; InlineComponent ic = new InlineComponent(n); start = G3DTools.getPoint(ic.getControlPoint().getPrevious().getLocalPosition()); end = G3DTools.getPoint(ic.getControlPoint().getNext().getLocalPosition()); Vector3d dir = new Vector3d(end); dir.sub(start); dir.scale(0.5); middle = new Point3d(start); middle.add(dir); monitorNode.setLocalTranslation(VecmathJmeTools.get(middle)); } else { return; } Node selectedParent = node.getGroup(); this.node = node; currentParent = selectedParent; monitorNode.removeFromParent(); currentParent.attachChild(monitorNode); provider.setSource(n); update(graph); } public IGraphicsNode getNode() { return node; } public void update() { if (useDistanceResize) { Vector3f v = VecmathJmeTools.get(editor.getCamera().getCameraPos()); v.subtractLocal(monitorNode.getWorldTranslation()); float length = v.length(); monitorNode.setLocalScale(length * 0.06f); } } public void update(Graph graph) { ArrayList titles = provider.getTexts(graph); graphics.clearRect(0, 0, monitorSize, monitorSize); int y = 16; for (String s : titles) { graphics.drawString(s, 0, y); y += 16; } TextureState ts = (TextureState) monitorNode .getRenderState(RenderState.RS_TEXTURE); ts.deleteAll(); // FIXME : texture won't be updated without this graphics.update(); update(); } public void remove() { monitorNode.removeFromParent(); node = null; } /** * if true, monitors size is independent of distance to camera. Else monitor's size changes when camera is moved. * @return */ public boolean isUseDistanceResize() { return useDistanceResize; } public void setUseDistanceResize(boolean useDistanceResize) { this.useDistanceResize = useDistanceResize; if (!useDistanceResize) { monitorNode.setLocalScale(1.f); } } public void setTextProvider(MonitorTextProvider provider) { this.provider = provider; } }