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 RenderDeviceJme(NiftyJmeDisplay display)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 setResourceLoader(NiftyResourceLoader niftyResourceLoader)105 public void setResourceLoader(NiftyResourceLoader niftyResourceLoader) { 106 } 107 setRenderManager(RenderManager rm)108 public void setRenderManager(RenderManager rm) { 109 this.rm = rm; 110 this.r = rm.getRenderer(); 111 } 112 113 // TODO: Cursor support createMouseCursor(String str, int x, int y)114 public MouseCursor createMouseCursor(String str, int x, int y) { 115 return new MouseCursor() { 116 117 public void dispose() { 118 } 119 }; 120 } 121 enableMouseCursor(MouseCursor cursor)122 public void enableMouseCursor(MouseCursor cursor) { 123 } 124 disableMouseCursor()125 public void disableMouseCursor() { 126 } 127 createImage(String filename, boolean linear)128 public RenderImage createImage(String filename, boolean linear) { 129 return new RenderImageJme(filename, linear, display); 130 } 131 createFont(String filename)132 public RenderFont createFont(String filename) { 133 return new RenderFontJme(filename, display); 134 } 135 beginFrame()136 public void beginFrame() { 137 } 138 endFrame()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 getWidth()148 public int getWidth() { 149 return display.getWidth(); 150 } 151 getHeight()152 public int getHeight() { 153 return display.getHeight(); 154 } 155 clear()156 public void clear() { 157 } 158 setBlendMode(BlendMode blendMode)159 public void setBlendMode(BlendMode blendMode) { 160 if (this.blendMode != blendMode) { 161 this.blendMode = blendMode; 162 } 163 } 164 convertBlend()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 convertColor(Color color)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 convertColor(Color inColor, ColorRGBA outColor)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 renderFont(RenderFont font, String str, int x, int y, Color color, float size)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 renderFont(RenderFont font, String str, int x, int y, Color color, float sizeX, float sizeY)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 renderImage(RenderImage image, int x, int y, int w, int h, int srcX, int srcY, int srcW, int srcH, Color color, float scale, int centerX, int centerY)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 renderImage(RenderImage image, int x, int y, int width, int height, Color color, float imageScale)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 renderQuad(int x, int y, int width, int height, Color color)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 renderQuad(int x, int y, int width, int height, Color topLeft, Color topRight, Color bottomRight, Color bottomLeft)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 enableClip(int x0, int y0, int x1, int y1)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 disableClip()377 public void disableClip() { 378 // System.out.println("disableClip"); 379 if (clipWasSet) { 380 r.clearClipRect(); 381 clipWasSet = false; 382 } 383 } 384 } 385