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 */ 32package com.jme3.niftygui; 33 34import com.jme3.font.BitmapText; 35import com.jme3.material.Material; 36import com.jme3.material.RenderState; 37import com.jme3.math.ColorRGBA; 38import com.jme3.math.Matrix4f; 39import com.jme3.renderer.RenderManager; 40import com.jme3.renderer.Renderer; 41import com.jme3.scene.Geometry; 42import com.jme3.scene.VertexBuffer; 43import com.jme3.scene.VertexBuffer.Format; 44import com.jme3.scene.VertexBuffer.Type; 45import com.jme3.scene.VertexBuffer.Usage; 46import com.jme3.scene.shape.Quad; 47import com.jme3.texture.Texture2D; 48import com.jme3.util.BufferUtils; 49import de.lessvoid.nifty.elements.render.TextRenderer.RenderFontNull; 50import de.lessvoid.nifty.render.BlendMode; 51import de.lessvoid.nifty.spi.render.MouseCursor; 52import de.lessvoid.nifty.spi.render.RenderDevice; 53import de.lessvoid.nifty.spi.render.RenderFont; 54import de.lessvoid.nifty.spi.render.RenderImage; 55import de.lessvoid.nifty.tools.Color; 56import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader; 57import java.nio.ByteBuffer; 58import java.nio.FloatBuffer; 59import java.util.HashMap; 60 61public 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