Home | History | Annotate | Download | only in niftygui
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 package com.jme3.niftygui;
     33 
     34 import com.jme3.font.BitmapText;
     35 import com.jme3.material.Material;
     36 import com.jme3.material.RenderState;
     37 import com.jme3.math.ColorRGBA;
     38 import com.jme3.math.Matrix4f;
     39 import com.jme3.renderer.RenderManager;
     40 import com.jme3.renderer.Renderer;
     41 import com.jme3.scene.Geometry;
     42 import com.jme3.scene.VertexBuffer;
     43 import com.jme3.scene.VertexBuffer.Format;
     44 import com.jme3.scene.VertexBuffer.Type;
     45 import com.jme3.scene.VertexBuffer.Usage;
     46 import com.jme3.scene.shape.Quad;
     47 import com.jme3.texture.Texture2D;
     48 import com.jme3.util.BufferUtils;
     49 import de.lessvoid.nifty.elements.render.TextRenderer.RenderFontNull;
     50 import de.lessvoid.nifty.render.BlendMode;
     51 import de.lessvoid.nifty.spi.render.MouseCursor;
     52 import de.lessvoid.nifty.spi.render.RenderDevice;
     53 import de.lessvoid.nifty.spi.render.RenderFont;
     54 import de.lessvoid.nifty.spi.render.RenderImage;
     55 import de.lessvoid.nifty.tools.Color;
     56 import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;
     57 import java.nio.ByteBuffer;
     58 import java.nio.FloatBuffer;
     59 import java.util.HashMap;
     60 
     61 public class RenderDeviceJme implements RenderDevice {
     62 
     63     private NiftyJmeDisplay display;
     64     private RenderManager rm;
     65     private Renderer r;
     66     private HashMap<String, BitmapText> textCacheLastFrame = new HashMap<String, BitmapText>();
     67     private HashMap<String, BitmapText> textCacheCurrentFrame = new HashMap<String, BitmapText>();
     68     private final Quad quad = new Quad(1, -1, true);
     69     private final Geometry quadGeom = new Geometry("nifty-quad", quad);
     70     private final Material niftyMat;
     71     private final Material niftyQuadMat;
     72     private final Material niftyQuadGradMat;
     73     private boolean clipWasSet = false;
     74     private BlendMode blendMode = null;
     75     private VertexBuffer quadDefaultTC = quad.getBuffer(Type.TexCoord);
     76     private VertexBuffer quadModTC = quadDefaultTC.clone();
     77     private VertexBuffer quadColor;
     78     private Matrix4f tempMat = new Matrix4f();
     79     private ColorRGBA tempColor = new ColorRGBA();
     80 
     81     public RenderDeviceJme(NiftyJmeDisplay display) {
     82         this.display = display;
     83 
     84         quadColor = new VertexBuffer(Type.Color);
     85         quadColor.setNormalized(true);
     86         ByteBuffer bb = BufferUtils.createByteBuffer(4 * 4);
     87         quadColor.setupData(Usage.Stream, 4, Format.UnsignedByte, bb);
     88         quad.setBuffer(quadColor);
     89 
     90         quadModTC.setUsage(Usage.Stream);
     91 
     92         //Color + texture color material for text and images
     93         niftyMat = new Material(display.getAssetManager(), "Common/MatDefs/Nifty/NiftyTex.j3md");
     94         niftyMat.getAdditionalRenderState().setDepthTest(false);
     95         //Color material for uniform colored quads
     96         niftyQuadMat = new Material(display.getAssetManager(), "Common/MatDefs/Nifty/NiftyQuad.j3md");
     97         niftyQuadMat.getAdditionalRenderState().setDepthTest(false);
     98 
     99         //vertex color only for gradient quads (although i didn't find a way in nifty to make a gradient using vertex color)
    100         niftyQuadGradMat = new Material(display.getAssetManager(), "Common/MatDefs/Nifty/NiftyQuadGrad.j3md");
    101         niftyQuadGradMat.getAdditionalRenderState().setDepthTest(false);
    102 
    103     }
    104 
    105     public void setResourceLoader(NiftyResourceLoader niftyResourceLoader) {
    106     }
    107 
    108     public void setRenderManager(RenderManager rm) {
    109         this.rm = rm;
    110         this.r = rm.getRenderer();
    111     }
    112 
    113     // TODO: Cursor support
    114     public MouseCursor createMouseCursor(String str, int x, int y) {
    115         return new MouseCursor() {
    116 
    117             public void dispose() {
    118             }
    119         };
    120     }
    121 
    122     public void enableMouseCursor(MouseCursor cursor) {
    123     }
    124 
    125     public void disableMouseCursor() {
    126     }
    127 
    128     public RenderImage createImage(String filename, boolean linear) {
    129         return new RenderImageJme(filename, linear, display);
    130     }
    131 
    132     public RenderFont createFont(String filename) {
    133         return new RenderFontJme(filename, display);
    134     }
    135 
    136     public void beginFrame() {
    137     }
    138 
    139     public void endFrame() {
    140         HashMap<String, BitmapText> temp = textCacheLastFrame;
    141         textCacheLastFrame = textCacheCurrentFrame;
    142         textCacheCurrentFrame = temp;
    143         textCacheCurrentFrame.clear();
    144 
    145 //        System.exit(1);
    146     }
    147 
    148     public int getWidth() {
    149         return display.getWidth();
    150     }
    151 
    152     public int getHeight() {
    153         return display.getHeight();
    154     }
    155 
    156     public void clear() {
    157     }
    158 
    159     public void setBlendMode(BlendMode blendMode) {
    160         if (this.blendMode != blendMode) {
    161             this.blendMode = blendMode;
    162         }
    163     }
    164 
    165     private RenderState.BlendMode convertBlend() {
    166         if (blendMode == null) {
    167             return RenderState.BlendMode.Off;
    168         } else if (blendMode == BlendMode.BLEND) {
    169             return RenderState.BlendMode.Alpha;
    170         } else if (blendMode == BlendMode.MULIPLY) {
    171             return RenderState.BlendMode.Modulate;
    172         } else {
    173             throw new UnsupportedOperationException();
    174         }
    175     }
    176 
    177     private int convertColor(Color color) {
    178         int color2 = 0;
    179         color2 |= ((int) (255.0 * color.getAlpha())) << 24;
    180         color2 |= ((int) (255.0 * color.getBlue())) << 16;
    181         color2 |= ((int) (255.0 * color.getGreen())) << 8;
    182         color2 |= ((int) (255.0 * color.getRed()));
    183         return color2;
    184     }
    185 
    186     private ColorRGBA convertColor(Color inColor, ColorRGBA outColor) {
    187         return outColor.set(inColor.getRed(), inColor.getGreen(), inColor.getBlue(), inColor.getAlpha());
    188     }
    189 
    190 //    private void setColor(Color color) {
    191 //        ByteBuffer buf = (ByteBuffer) quadColor.getData();
    192 //        buf.rewind();
    193 //
    194 //        int color2 = convertColor(color);
    195 //        buf.putInt(color2);
    196 //        buf.putInt(color2);
    197 //        buf.putInt(color2);
    198 //        buf.putInt(color2);
    199 //
    200 //        buf.flip();
    201 //        quadColor.updateData(buf);
    202 //    }
    203 
    204     /**
    205      *
    206      * @param font
    207      * @param str
    208      * @param x
    209      * @param y
    210      * @param color
    211      * @param size
    212      * @deprecated use renderFont(RenderFont font, String str, int x, int y, Color color, float sizeX, float sizeY) instead
    213      */
    214     @Deprecated
    215     public void renderFont(RenderFont font, String str, int x, int y, Color color, float size) {
    216         renderFont(font, str, x, y, color, size, size);
    217     }
    218 
    219     @Override
    220     public void renderFont(RenderFont font, String str, int x, int y, Color color, float sizeX, float sizeY) {
    221         if (str.length() == 0) {
    222             return;
    223         }
    224 
    225         if (font instanceof RenderFontNull) {
    226             return;
    227         }
    228 
    229         RenderFontJme jmeFont = (RenderFontJme) font;
    230 
    231         String key = font + str + color.getColorString();
    232         BitmapText text = textCacheLastFrame.get(key);
    233         if (text == null) {
    234             text = jmeFont.createText();
    235             text.setText(str);
    236             text.updateLogicalState(0);
    237         }
    238         textCacheCurrentFrame.put(key, text);
    239 
    240         niftyMat.setColor("Color", convertColor(color, tempColor));
    241         niftyMat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
    242 //        niftyMat.getAdditionalRenderState().setBlendMode(convertBlend());
    243         text.setMaterial(niftyMat);
    244 
    245         tempMat.loadIdentity();
    246         tempMat.setTranslation(x, getHeight() - y, 0);
    247         tempMat.setScale(sizeX, sizeY, 0);
    248 
    249         rm.setWorldMatrix(tempMat);
    250         text.render(rm);
    251 
    252 //        System.out.println("renderFont");
    253     }
    254 
    255     public void renderImage(RenderImage image, int x, int y, int w, int h,
    256             int srcX, int srcY, int srcW, int srcH,
    257             Color color, float scale,
    258             int centerX, int centerY) {
    259         RenderImageJme jmeImage = (RenderImageJme) image;
    260         Texture2D texture = jmeImage.getTexture();
    261 
    262         niftyMat.getAdditionalRenderState().setBlendMode(convertBlend());
    263         niftyMat.setColor("Color", convertColor(color, tempColor));
    264         niftyMat.setTexture("Texture", texture);
    265         //setColor(color);
    266 
    267         float imageWidth = jmeImage.getWidth();
    268         float imageHeight = jmeImage.getHeight();
    269         FloatBuffer texCoords = (FloatBuffer) quadModTC.getData();
    270 
    271         float startX = srcX / imageWidth;
    272         float startY = srcY / imageHeight;
    273         float endX = startX + (srcW / imageWidth);
    274         float endY = startY + (srcH / imageHeight);
    275 
    276         startY = 1f - startY;
    277         endY = 1f - endY;
    278 
    279         texCoords.rewind();
    280         texCoords.put(startX).put(startY);
    281         texCoords.put(endX).put(startY);
    282         texCoords.put(endX).put(endY);
    283         texCoords.put(startX).put(endY);
    284         texCoords.flip();
    285         quadModTC.updateData(texCoords);
    286 
    287         quad.clearBuffer(Type.TexCoord);
    288         quad.setBuffer(quadModTC);
    289 
    290         float x0 = centerX + (x - centerX) * scale;
    291         float y0 = centerY + (y - centerY) * scale;
    292 
    293         tempMat.loadIdentity();
    294         tempMat.setTranslation(x0, getHeight() - y0, 0);
    295         tempMat.setScale(w * scale, h * scale, 0);
    296 
    297         rm.setWorldMatrix(tempMat);
    298         niftyMat.render(quadGeom, rm);
    299 //
    300 //        System.out.println("renderImage (Sub)");
    301     }
    302 
    303     public void renderImage(RenderImage image, int x, int y, int width, int height,
    304             Color color, float imageScale) {
    305 
    306         RenderImageJme jmeImage = (RenderImageJme) image;
    307 
    308         niftyMat.getAdditionalRenderState().setBlendMode(convertBlend());
    309         niftyMat.setColor("Color", convertColor(color, tempColor));
    310         niftyMat.setTexture("Texture", jmeImage.getTexture());
    311         //setColor(color);
    312 
    313         quad.clearBuffer(Type.TexCoord);
    314         quad.setBuffer(quadDefaultTC);
    315 
    316         float x0 = x + 0.5f * width * (1f - imageScale);
    317         float y0 = y + 0.5f * height * (1f - imageScale);
    318 
    319         tempMat.loadIdentity();
    320         tempMat.setTranslation(x0, getHeight() - y0, 0);
    321         tempMat.setScale(width * imageScale, height * imageScale, 0);
    322 
    323         rm.setWorldMatrix(tempMat);
    324         niftyMat.render(quadGeom, rm);
    325 //
    326 //        System.out.println("renderImage");
    327     }
    328 
    329     public void renderQuad(int x, int y, int width, int height, Color color) {
    330         if (color.getAlpha() > 0) {
    331             niftyQuadMat.getAdditionalRenderState().setBlendMode(convertBlend());
    332             niftyQuadMat.setColor("Color", convertColor(color, tempColor));
    333 
    334             tempMat.loadIdentity();
    335             tempMat.setTranslation(x, getHeight() - y, 0);
    336             tempMat.setScale(width, height, 0);
    337 
    338             rm.setWorldMatrix(tempMat);
    339             niftyQuadMat.render(quadGeom, rm);
    340         }
    341 //        System.out.println("renderQuad (Solid)");
    342     }
    343 
    344     public void renderQuad(int x, int y, int width, int height,
    345             Color topLeft, Color topRight, Color bottomRight, Color bottomLeft) {
    346 
    347         ByteBuffer buf = (ByteBuffer) quadColor.getData();
    348         buf.rewind();
    349 
    350         buf.putInt(convertColor(topRight));
    351         buf.putInt(convertColor(topLeft));
    352 
    353         buf.putInt(convertColor(bottomLeft));
    354         buf.putInt(convertColor(bottomRight));
    355 
    356         buf.flip();
    357         quadColor.updateData(buf);
    358 
    359         niftyQuadGradMat.getAdditionalRenderState().setBlendMode(convertBlend());
    360 
    361         tempMat.loadIdentity();
    362         tempMat.setTranslation(x, getHeight() - y, 0);
    363         tempMat.setScale(width, height, 0);
    364 
    365         rm.setWorldMatrix(tempMat);
    366         niftyQuadGradMat.render(quadGeom, rm);
    367 //
    368 //        System.out.println("renderQuad (Grad)");
    369     }
    370 
    371     public void enableClip(int x0, int y0, int x1, int y1) {
    372 //        System.out.println("enableClip");
    373         clipWasSet = true;
    374         r.setClipRect(x0, getHeight() - y1, x1 - x0, y1 - y0);
    375     }
    376 
    377     public void disableClip() {
    378 //        System.out.println("disableClip");
    379         if (clipWasSet) {
    380             r.clearClipRect();
    381             clipWasSet = false;
    382         }
    383     }
    384 }
    385