Package org.mt4j.util

Source Code of org.mt4j.util.SwingTextureRenderer

/***********************************************************************
* mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.util;

import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.CellRendererPane;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

import org.mt4j.MTApplication;
import org.mt4j.util.opengl.GLTextureSettings;
import org.mt4j.util.opengl.GLTexture;
import org.mt4j.util.opengl.GLTexture.EXPANSION_FILTER;
import org.mt4j.util.opengl.GLTexture.SHRINKAGE_FILTER;
import org.mt4j.util.opengl.GLTexture.WRAP_MODE;

import processing.core.PImage;

/**
* This class can be used to render java swing JComponents to an
* OpenGL texture. So this can at the moment only be used in OpenGL.
* <br>After instantiating this class the component will be rendered
* by a call to <code>scheduleRefresh()</code>.
* The OpenGL texture can then be retrieved by the
* <code>getTextureToRenderTo()</code> method.
* <p>Note:
* Order of adding components is the order in which they appear in z-order
* -> add ontop comps first
* <p>Note:
* The JComponents can only be displayed if setBounds or setSize is called with positive values
* (probably only neccessary when using no layoutManager).
*
* @author Christopher Ruff
*/
public class SwingTextureRenderer {
 
  /** The comp to draw. */
  private Component compToDraw;
 
  /** The mt app. */
  private MTApplication mtApp;

  /** The texture to render to. */
  private GLTexture textureToRenderTo;

  /** The temp image. */
  private PImage tempImage;
 
  /** The tmp bounds rect. */
  private Rectangle tmpBoundsRect;

  /** The t. */
  private Timer t;
 
  private List<ActionListener> paintedListeners;


  //TODO enable non OpenGL version
  /**
   * The Constructor.
   *
   * @param mtApp the mt app
   * @param compToRender the comp to render into texture
   */
  public SwingTextureRenderer(MTApplication mtApp, Component compToRender) {
    super();
    this.compToDraw = compToRender;
    this.mtApp = mtApp;
   
    paintedListeners = new ArrayList<ActionListener>();
   
    this.tmpBoundsRect = new Rectangle();
   
    //Add component to PApplet
    //make comptoDraw invisible to not actually show it on screen
    compToDraw.setVisible(false);
    mtApp.add(compToDraw);

//    MouseEvent me = new MouseEvent(
//        compToDraw, //Source == dispatch comp?
//        MouseEvent.MOUSE_PRESSED,
//        System.currentTimeMillis(),
//        MouseEvent.BUTTON1_MASK,
//        10, 10,
//        1,
//        false);
//    compToDraw.dispatchEvent(me);
   
  //Create the texture
////    notVisibleImage = new PImage(rectC.width, rectC.height);
//      GLTextureParameters tp = new GLTextureParameters();
//      tp.minFilter = GLConstants.LINEAR; //To avoid mipmapgeneration at each update
////      tp.minFilter = GLConstants.LINEAR_MIPMAP_LINEAR; //For mip maps
//      tp.magFilter = GLConstants.LINEAR;
//     
      final Rectangle rectC = SwingUtilities.getLocalBounds(compToDraw);
//      textureToRenderTo = new GLTexture(mtApp, rectC.width, rectC.height, tp, false);
//
//      //TODO check if we are in the rendering thread or not
//      if (!mtApp.isRenderThreadCurrent()){
//        mtApp.invokeLater(new Runnable() {
//            public void run() {
//              textureToRenderTo.initTexture(rectC.width, rectC.height);
//            }
//          });
//      }
     
      GLTextureSettings ts = new GLTextureSettings();
      ts.shrinkFilter = SHRINKAGE_FILTER.BilinearNoMipMaps;
//      ts.shrinkFilter = SHRINKAGE_FILTER.Trilinear; //For better quality
      ts.expansionFilter = EXPANSION_FILTER.Bilinear;
      ts.wrappingHorizontal = WRAP_MODE.CLAMP_TO_EDGE;
      ts.wrappingVertical = WRAP_MODE.CLAMP_TO_EDGE;
    
      textureToRenderTo = new GLTexture(mtApp, ts);
//      textureToRenderTo = new MTTexture(mtApp, rectC.width, rectC.height, ts); //This would also init the gl texture
      textureToRenderTo.width = rectC.width; //So that tex coords of shape get scaled correctly
      textureToRenderTo.height = rectC.height;
     
      if (!mtApp.isRenderThreadCurrent()){
        mtApp.invokeLater(new Runnable() {
            public void run() {
//              textureToRenderTo.initTexture(rectC.width, rectC.height);
              textureToRenderTo.setupGLTexture(rectC.width, rectC.height);
            }
          });
      }else{
//        textureToRenderTo.initTexture(rectC.width, rectC.height);
        textureToRenderTo.setupGLTexture(rectC.width, rectC.height);
      }
    
//    this.scheduleRefresh(); //ENABLE?
  }
 
 
  /**
   * Gets the texture to render to.
   *
   * @return the texture to render to
   */
  public GLTexture getTextureToRenderTo(){
    return this.textureToRenderTo;
  }
 
  /**
   * Start timed refresh.
   *
   * @param time the time
   */
  public void startTimedRefresh(int time){
    t = new Timer(time, new ActionListener() {
      //@Override
      public void actionPerformed(ActionEvent arg0) {
        scheduleRefresh();
      }
    });
    t.start();
  }
 
  /**
   * Stop timer.
   */
  public void stopTimedRefresh(){
    if (t!=null){
      t.stop();
    }
  }
 
 
  /**
   * This schedules a new pass of rendering the JComponent into a texture.
   * Use this to render the component into the texture or to update the texture if the
   * JComponent changed.
   */
  public void scheduleRefresh(){
//    try {
//      SwingUtilities.invokeAndWait(new Runnable(){
    SwingUtilities.invokeLater(new Runnable(){
        //@Override
        public void run() {
          Rectangle boundingRect = SwingUtilities.getLocalBounds(compToDraw);
          //System.out.println("BoundingRect w:" + boundingRect.width + " h:" + boundingRect.height);
          //FIXME as the 2nd parameter container, really use the parent?
          paintComponentOffscreen(compToDraw, compToDraw.getParent(), boundingRect);
         
          firePaintOccurred();
        }
     });
//    } catch (InterruptedException e) {
//      e.printStackTrace();
//    } catch (InvocationTargetException e) {
//      e.printStackTrace();
//    }
  }
 
 
  private BufferedImage img;
  private Graphics2D g; //TODO dispose by hand!
  CellRendererPane crp;
 
  /**
   * Paint not visible component.
   *
   * @param c the c
   * @param con the con
   * @param rect the rect
   *
   * @return the buffered image
   */
  private BufferedImage paintComponentOffscreen(Component c, Container con, Rectangle rect) {
    //FIXME n�tig? paintComponent added anscheinend c nochmal zu con!?
    con.remove(c);
    /*
    BufferedImage img = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_ARGB); 
    Graphics2D g = img.createGraphics();
    */
    //Lazily initialize
    if (img == null){
      img = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_ARGB);
    }
    if (g == null){
      g = img.createGraphics();
    }
   
    if (c instanceof JComponent) {
      JComponent jComp = (JComponent) c;
      jComp.setOpaque(false);
    }
    /*
    if (!c.isLightweight()){
      System.err.println("Component to paint (" + c.getName() + ") is not lightweight -> undeterministic behaviour!");
    }
    */
   
//    SwingUtilities.paintComponent(g, c, con, rect); 
    //The following does what SwingUtilities.paintComponent does
    if (crp == null){
      crp = new CellRendererPane();
    }
    crp.add(c);
    con.add(crp);
    crp.paintComponent(g, c, con, rect.x, rect.y, rect.width, rect.height, false);
    //FIXME TEST, BENEFITS?
    con.remove(crp);
    crp.remove(c);
    con.add(c);
   
    //Dispose graphics context
//    g.dispose();  //reuse context!
   
    //Bug? c's bounds get changed by the paintComponent method!?
    //This is a hack that seems to fix it
    c.getBounds(tmpBoundsRect);
    c.setBounds(tmpBoundsRect.width, tmpBoundsRect.height, Math.abs(tmpBoundsRect.x), Math.abs(tmpBoundsRect.y));
   
    //TODO evtl direkt in Intbuffer schreiben ohne PImage
//    this.tempImage = new PImage(img);
   
//    /*
    //Put buffered image into PImage pixels
     BufferedImage bi = img;
        int width = bi.getWidth();
        int height = bi.getHeight();
        if (tempImage == null){
          tempImage = new PImage(width, height);
          tempImage.loadPixels();
        }
        WritableRaster raster = bi.getRaster();
        raster.getDataElements(0, 0, width, height, tempImage.pixels);
//    */

    //Refresh GL texture next draw
    mtApp.invokeLater(new Runnable() {
      //@Override
      public void run() {
//        textureToRenderTo.putPixelsIntoTexture(tempImage); //OpenGL
//        textureToRenderTo.putImage(tempImage); //SLOWER but also fills the PImage pixels[] with the image
        //firePaintOccurred();
        textureToRenderTo.loadGLTexture(tempImage); //OpenGL
       
      }
    });
    return img; 
 

 
  private void firePaintOccurred(){
    for (Iterator<ActionListener> iterator = paintedListeners.iterator(); iterator.hasNext();) {
      ActionListener a = iterator.next();
      a.actionPerformed(new ActionEvent(this, 0,""));
    }
  }
 
  public void addPaintOcurredListener(ActionListener a){
    this.paintedListeners.add(a);
  }
 
  public void removePaintOcurredListener(ActionListener a){
    if (this.paintedListeners.contains(a)){
      this.paintedListeners.remove(a);
    }
  }
 
 

  /*
    //Swing render usage example:
    // Render swing component to texture \\
    
    JPanel panel1 = new JPanel(true);
    panel1.setVisible(false);
    panel1.setBounds(0,0,200,200);
   
  //Button
  b = new B();
  b.setBounds(0,0,100,100);
  b.setText("Hello");
   
    JTextArea t = new JTextArea("text!");
    t.setBounds(100,100,50,50);
   
    JPanel innerP = new JPanel();
    innerP.setBackground(new Color(120));
    innerP.setBounds(0,0,150,150);
   
    JButton otherButton = new JButton("lorem ipsum");
    otherButton.setBounds(0,0, 120,120);
    innerP.add(otherButton);
   
    panel1.add(b);
    panel1.add(innerP);
    panel1.add(t);
   
    //Simulate mouse down on the button
    b.dispatchEvent(new MouseEvent(b, MouseEvent.MOUSE_PRESSED, 0, MouseEvent.BUTTON1_MASK, 10,10, 40,40, 1, false, MouseEvent.BUTTON1));
   
    swingTex = new SwingTextureRenderer(pa, panel1);
   
    MTRectangle rectangle = new MTRectangle(300,300,0, 200,200, pa);
    rectangle.setTexture(swingTex.getTextureToRenderTo());
    this.getCanvas().addChild(rectangle);
    */
 
}
 
TOP

Related Classes of org.mt4j.util.SwingTextureRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.