用JMonkey最大的问题就是中文问题,IDE不是中文没关系,反正可以迁移到Idea里,但是打包发布的项目以及Nifty做的GUI里没有中文就心塞塞了。好在找到一篇前两年的博客,叫JME3与NIFTY GUI1.3结合,修改使其支持中文的输入与显示,里面有大神解决过该问题,虽然他的版本有些老,很多语句和新的不太一样,但帮了很大忙。

源代码修改

看过前两篇的同学就知道,我使用gradle管理的依赖,现在要改源代码,所以就要把原项目作为一个项目依赖,试了很久没成功,干脆把原项目重新打开,修改完源码以后自己打个包,再导入项目,开源项目就是方便。原项目也是用gradle管理的,打包也很方便,到github上拉下来就好。
打开以后是这个样子:

  • 修改jme3-lwjgl中的com.jme3.input.lwjgl.LwjglKeyInput.java中的update方法,直接copy下面代码即可。
/** Copyright (c) 2009-2012 jMonkeyEngine* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are* met:** * Redistributions of source code must retain the above copyright*   notice, this list of conditions and the following disclaimer.** * Redistributions in binary form must reproduce the above copyright*   notice, this list of conditions and the following disclaimer in the*   documentation and/or other materials provided with the distribution.** * Neither the name of 'jMonkeyEngine' nor the names of its contributors*   may be used to endorse or promote products derived from this software*   without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/package com.jme3.input.lwjgl;import com.jme3.input.KeyInput;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.RawInputListener;
import com.jme3.system.lwjgl.LwjglAbstractDisplay;
import com.jme3.system.lwjgl.LwjglTimer;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;import javax.swing.*;public class LwjglKeyInput implements KeyInput {private static final Logger logger = Logger.getLogger(LwjglKeyInput.class.getName());private LwjglAbstractDisplay context;private RawInputListener listener;public LwjglKeyInput(LwjglAbstractDisplay context){this.context = context;}public void initialize() {if (!context.isRenderable())return;try {Keyboard.create();Keyboard.enableRepeatEvents(true);logger.fine("Keyboard created.");} catch (LWJGLException ex) {logger.log(Level.SEVERE, "Error while creating keyboard.", ex);}}public int getKeyCount(){return Keyboard.KEYBOARD_SIZE;}char chcode = 0;public void update() {if (!context.isRenderable())return;Keyboard.poll();while (Keyboard.next()){
//            int keyCode = Keyboard.getEventKey();
//            char keyChar = Keyboard.getEventCharacter();
//            boolean pressed = Keyboard.getEventKeyState();
//            boolean down = Keyboard.isRepeatEvent();
//            long time = Keyboard.getEventNanoseconds();
//            KeyInputEvent evt = new KeyInputEvent(keyCode, keyChar, pressed, down);
//            evt.setTime(time);
//            listener.onKeyEvent(evt);//若接受到的是中文char character = Keyboard.getEventCharacter();if (chcode == 0) {chcode = character;if (character > 127) {return;}} else {chcode = (char) (character + (chcode << 8));}try {SwingUtilities.invokeAndWait(new Runnable() {public void run() {long time = Keyboard.getEventNanoseconds();if (Keyboard.getEventKeyState()) // if pressed{sendEvent(time, Keyboard.getEventKey(), chcode, true);} else {sendEvent(time, Keyboard.getEventKey(), chcode, false);}chcode = 0;}});} catch (InterruptedException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}private Map<Int, Char> characters = new HashMap<Int, Char>();private static Int anInt = new Int(0);private void handEvent(long time, int keyCode, char character, boolean pressed) {KeyInputEvent evt = new KeyInputEvent(keyCode, character, pressed, Keyboard.isRepeatEvent());evt.setTime(time);listener.onKeyEvent(evt);}private void sendEvent(long time, int keyCode2, char character, boolean pressed) {int keyCode = com.jme3.input.awt.AwtKeyInput.convertJmeCode(keyCode2);try {if (keyCode != 0) {
//                if (character == '\0') {//                    character = KeyEvent.CHAR_UNDEFINED;
//                }if (pressed) {
//                    if (character != KeyEvent.CHAR_UNDEFINED) {if (character <= 255) {//英文和特殊字符,即之前不支持中文时的字符handEvent(time, keyCode2, character, pressed);}anInt.value = keyCode;Char c = characters.get(anInt);if (c == null) {characters.put(new Int(keyCode), new Char(character));} else {c.value = character;}}if (!pressed) {anInt.value = keyCode;if (character > 255 && character < 65535) {char s = new String(new byte[]{(byte) (character / 256), (byte) (character % 256)}, "gbk").toCharArray()[0];//中文handEvent(time, keyCode, s, true);handEvent(time, keyCode, s, false);} else {//英文和特殊字符,即之前不支持中文时的字符handEvent(time, keyCode2, character, false);}}}} catch (Exception e) {
//             logger.info("");}}private static class Int {public Int(int value) {this.value = value;}public boolean equals(Object obj) {return obj instanceof Int && ((Int) obj).value == value;}public int hashCode() {return value;}int value;}private static class Char {public Char(char value) {this.value = value;}char value;}public void destroy() {if (!context.isRenderable())return;Keyboard.destroy();logger.fine("Keyboard destroyed.");}public boolean isInitialized() {return Keyboard.isCreated();}public void setInputListener(RawInputListener listener) {this.listener = listener;}public long getInputTimeNanos() {return Sys.getTime() * LwjglTimer.LWJGL_TIME_TO_NANOS;}}
  • 在jme3-niftygui中的com.jme3.niftygui中新建类RenderFontAWT.java,直接copy下面代码即可:
package com.jme3.niftygui;import de.lessvoid.nifty.spi.render.RenderFont;import javax.annotation.Nonnull;
import java.awt.*;
import java.awt.image.BufferedImage;public class RenderFontAWT implements RenderFont {private FontMetrics fontMetrics;public RenderFontAWT() {BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);Font awtFont = new Font("黑体", java.awt.Font.PLAIN, 12);fontMetrics = image.createGraphics().getFontMetrics(awtFont);}@Overridepublic int getWidth(String text) {if (text.length() == 0) {return 0;}return fontMetrics.stringWidth(text);}@Overridepublic int getWidth(@Nonnull String text, float size) {return 0;}@Overridepublic int getHeight() {return (fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent());}@Overridepublic int getCharacterAdvance(char currentCharacter, char nextCharacter, float size) {return -1;}@Overridepublic void dispose() {//To change body of implemented methods use File | Settings | File Templates.}
}
  • 在jme3-niftygui中的com.jme3.niftygui中新建类RenderDeviceAWT.java,直接copy下面代码即可:
package com.jme3.niftygui;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix4f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Format;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.util.BufferUtils;
import de.lessvoid.nifty.render.BlendMode;
import de.lessvoid.nifty.spi.render.*;
import de.lessvoid.nifty.tools.Color;
import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;import javax.annotation.Nonnull;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
public class RenderDeviceAWT implements RenderDevice {private FontMetrics fontMetrics;private Font awtFont = null;private NiftyJmeDisplay display;private RenderManager rm;private Renderer r;private final Quad quad= new Quad(1, -1, true);private final Geometry quadGeom= new Geometry("nifty-quad", quad);private RenderState renderState = new RenderState();private Material colorMaterial;private Material textureColorMaterial;private Material vertexColorMaterial;private boolean clipWasSet = false;private BlendMode blendMode = null;private VertexBuffer quadDefaultTC = quad.getBuffer(Type.TexCoord);private VertexBuffer quadModTC = quadDefaultTC.clone();private VertexBuffer quadColor;private Matrix4f tempMat = new Matrix4f();private ColorRGBA tempColor = new ColorRGBA();public RenderDeviceAWT(NiftyJmeDisplay display) {this.display = display;BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);awtFont = new Font("黑体", java.awt.Font.PLAIN, 12);fontMetrics = image.createGraphics().getFontMetrics(awtFont);quadColor = new VertexBuffer(Type.Color);quadColor.setNormalized(true);ByteBuffer bb = BufferUtils.createByteBuffer(4 * 4);quadColor.setupData(Usage.Stream, 4, Format.UnsignedByte, bb);quad.setBuffer(quadColor);quadModTC.setUsage(Usage.Stream);// Load the 3 material types separately to avoid// reloading the shader when the defines change.// Material with a single color (no texture or vertex color)colorMaterial = new Material(display.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");// Material with a texture and a color (no vertex color)textureColorMaterial = new Material(display.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");// Material with vertex color, used for gradients (no texture)vertexColorMaterial = new Material(display.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");vertexColorMaterial.setBoolean("VertexColor", true);// Shared render state for all materialsrenderState.setDepthTest(false);renderState.setDepthWrite(false);}@Overridepublic void setResourceLoader(@Nonnull NiftyResourceLoader niftyResourceLoader) {}public void setRenderManager(RenderManager rm) {this.rm = rm;this.r = rm.getRenderer();}// TODO: Cursor supportpublic MouseCursor createMouseCursor(String str, int x, int y){return new MouseCursor() {@Overridepublic void enable() {}@Overridepublic void disable() {}public void dispose() {}};}public void enableMouseCursor(MouseCursor cursor){}public void disableMouseCursor(){}public RenderImage createImage(String filename, boolean linear) {return new RenderImageJme(filename, linear, display);}public RenderFont createFont(String filename) {
//        return new RenderFontJme(filename, display);return new RenderFontAWT();}public void beginFrame() {}public void endFrame() {}public int getWidth() {return display.getWidth();}public int getHeight() {return display.getHeight();}public void clear() {}public void setBlendMode(BlendMode blendMode) {renderState.setBlendMode(convertBlend(blendMode));}private RenderState.BlendMode convertBlend(BlendMode blendMode) {if (blendMode == null) {return RenderState.BlendMode.Off;} else if (blendMode == BlendMode.BLEND) {return RenderState.BlendMode.Alpha;} else if (blendMode == BlendMode.MULIPLY) {return RenderState.BlendMode.Modulate;} else {throw new UnsupportedOperationException();}}private int convertColor(Color color){int color2 = 0;color2 |= ((int)(255.0 * color.getAlpha())) << 24;color2 |= ((int)(255.0 * color.getBlue())) << 16;color2 |= ((int)(255.0 * color.getGreen())) << 8;color2 |= ((int)(255.0 * color.getRed()));return color2;}private ColorRGBA convertColor(Color inColor, ColorRGBA outColor){return outColor.set(inColor.getRed(), inColor.getGreen(), inColor.getBlue(), inColor.getAlpha());}private void setColor(Color color){ByteBuffer buf = (ByteBuffer) quadColor.getData();buf.rewind();int color2 = convertColor(color);buf.putInt(color2);buf.putInt(color2);buf.putInt(color2);buf.putInt(color2);buf.flip();quadColor.updateData(buf);}@Overridepublic void renderFont(@Nonnull RenderFont font, @Nonnull String text, int x, int y,@Nonnull Color fontColor, float sizeX, float sizeY) {
//多行时还不知道有没有问题if (text.length() == 0) {return;}
//        if (font instanceof TextRenderer.RenderFontNull) {//            return;
//        }Texture texture = createTexture2D(text);// WARNING: Not compatible with OpenGL1 implementations..textureColorMaterial.setColor("Color", convertColor(fontColor, tempColor));textureColorMaterial.setBoolean("VertexColor", true);textureColorMaterial.setTexture("ColorMap", texture);
//        niftyMat.setInt("m_Mode", 3);float width = texture.getImage().getWidth();float height = texture.getImage().getHeight();Mesh text1 = new Quad(width, height);Geometry text2 = new Geometry("text", text1);float x0 = x + 0.5f * width * (1f - sizeX);float y0 = y + 0.5f * height * (1f - sizeX) + height;tempMat.loadIdentity();tempMat.setTranslation(x0, getHeight() - y0, 0);tempMat.setScale(sizeX, sizeY, 0);rm.setWorldMatrix(tempMat);textureColorMaterial.render(text2, rm);}private Texture2D createTexture2D(String str) {BufferedImage bi = new BufferedImage(fontMetrics.stringWidth(str), fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent(),BufferedImage.TYPE_INT_ARGB);java.awt.Color renderColor = java.awt.Color.WHITE;Graphics2D g = (Graphics2D) bi.getGraphics();g.setColor(renderColor);g.setBackground(java.awt.Color.WHITE);g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);g.setFont(awtFont);g.drawString(str, 0, fontMetrics.getMaxAscent() - 1);Texture2D texture2d = new Texture2D(load(bi, true));texture2d.setMagFilter(Texture.MagFilter.Bilinear);texture2d.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);return texture2d;}private com.jme3.texture.Image load(BufferedImage img, boolean flipY) {int width = img.getWidth();int height = img.getHeight();switch (img.getType()) {case BufferedImage.TYPE_3BYTE_BGR: // most common in JPEG imagesbyte[] dataBuf = extractImageData(img);if (flipY) {flipImage(dataBuf, width, height, 24);}ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth() * img.getHeight() * 3);data.put(dataBuf);return new com.jme3.texture.Image(com.jme3.texture.Image.Format.BGR8, width, height, data);case BufferedImage.TYPE_BYTE_GRAY: // grayscale fontsbyte[] dataBuf2 = extractImageData(img);if (flipY) {flipImage(dataBuf2, width, height, 8);}ByteBuffer data2 = BufferUtils.createByteBuffer(img.getWidth() * img.getHeight());data2.put(dataBuf2);return new com.jme3.texture.Image(com.jme3.texture.Image.Format.Luminance8, width, height, data2);default:break;}if (img.getTransparency() == Transparency.OPAQUE) {ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth() * img.getHeight() * 3);// no alphafor (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int ny = y;if (flipY) {ny = height - y - 1;}int rgb = img.getRGB(x, ny);byte r = (byte) ((rgb & 0x00FF0000) >> 16);byte g = (byte) ((rgb & 0x0000FF00) >> 8);byte b = (byte) ((rgb & 0x000000FF));data.put(r).put(g).put(b);}}data.flip();return new com.jme3.texture.Image(com.jme3.texture.Image.Format.RGB8, width, height, data);} else {ByteBuffer data = BufferUtils.createByteBuffer(img.getWidth() * img.getHeight() * 4);// no alphafor (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int ny = y;if (flipY) {ny = height - y - 1;}int rgb = img.getRGB(x, ny);byte a = (byte) ((rgb & 0xFF000000) >> 24);byte r = (byte) ((rgb & 0x00FF0000) >> 16);byte g = (byte) ((rgb & 0x0000FF00) >> 8);byte b = (byte) ((rgb & 0x000000FF));data.put(r).put(g).put(b).put(a);}}data.flip();return new com.jme3.texture.Image(com.jme3.texture.Image.Format.RGBA8, width, height, data);}}private byte[] extractImageData(BufferedImage img) {DataBuffer buf = img.getRaster().getDataBuffer();switch (buf.getDataType()) {case DataBuffer.TYPE_BYTE:DataBufferByte byteBuf = (DataBufferByte) buf;return byteBuf.getData();}return null;}private void flipImage(byte[] img, int width, int height, int bpp) {int scSz = (width * bpp) / 8;byte[] sln = new byte[scSz];int y2;for (int y1 = 0; y1 < height / 2; y1++) {y2 = height - y1 - 1;System.arraycopy(img, y1 * scSz, sln, 0, scSz);System.arraycopy(img, y2 * scSz, img, y1 * scSz, scSz);System.arraycopy(sln, 0, img, y2 * scSz, scSz);}}public void 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) {RenderImageJme jmeImage = (RenderImageJme) image;Texture2D texture = jmeImage.getTexture();textureColorMaterial.setColor("Color", convertColor(color, tempColor));textureColorMaterial.setTexture("ColorMap", texture);setColor(color);float imageWidth = texture.getImage().getWidth();float imageHeight = texture.getImage().getHeight();FloatBuffer texCoords = (FloatBuffer) quadModTC.getData();float startX = srcX / imageWidth;float startY = srcY / imageHeight;float endX = startX + (srcW / imageWidth);float endY = startY + (srcH / imageHeight);startY = 1f - startY;endY = 1f - endY;texCoords.rewind();texCoords.put(startX).put(startY);texCoords.put(endX).put(startY);texCoords.put(endX).put(endY);texCoords.put(startX).put(endY);texCoords.flip();quadModTC.updateData(texCoords);quad.clearBuffer(VertexBuffer.Type.TexCoord);quad.setBuffer(quadModTC);float x0 = centerX + (x - centerX) * scale;float y0 = centerY + (y - centerY) * scale;tempMat.loadIdentity();tempMat.setTranslation(x0, getHeight() - y0, 0);tempMat.setScale(w * scale, h * scale, 0);rm.setWorldMatrix(tempMat);rm.setForcedRenderState(renderState);textureColorMaterial.render(quadGeom, rm);}public void renderImage(RenderImage image, int x, int y, int width, int height,Color color, float imageScale) {RenderImageJme jmeImage = (RenderImageJme) image;textureColorMaterial.setColor("Color", convertColor(color, tempColor));textureColorMaterial.setTexture("ColorMap", jmeImage.getTexture());textureColorMaterial.setBoolean("VertexColor", true);setColor(color);quad.clearBuffer(VertexBuffer.Type.TexCoord);quad.setBuffer(quadDefaultTC);float x0 = x + 0.5f * width * (1f - imageScale);float y0 = y + 0.5f * height * (1f - imageScale);tempMat.loadIdentity();tempMat.setTranslation(x0, getHeight() - y0, 0);tempMat.setScale(width * imageScale, height * imageScale, 0);rm.setWorldMatrix(tempMat);rm.setForcedRenderState(renderState);textureColorMaterial.render(quadGeom, rm);}public void renderQuad(int x, int y, int width, int height, Color color) {if(color.getAlpha() >0){colorMaterial.setColor("Color", convertColor(color, tempColor));tempMat.loadIdentity();tempMat.setTranslation(x, getHeight() - y, 0);tempMat.setScale(width, height, 0);rm.setWorldMatrix(tempMat);rm.setForcedRenderState(renderState);colorMaterial.render(quadGeom, rm);}}public void renderQuad(int x, int y, int width, int height,Color topLeft, Color topRight, Color bottomRight, Color bottomLeft) {ByteBuffer buf = (ByteBuffer) quadColor.getData();buf.rewind();buf.putInt(convertColor(bottomRight));buf.putInt(convertColor(bottomLeft));buf.putInt(convertColor(topLeft));buf.putInt(convertColor(topRight));buf.flip();quadColor.updateData(buf);tempMat.loadIdentity();tempMat.setTranslation(x, getHeight() - y, 0);tempMat.setScale(width, height, 0);rm.setWorldMatrix(tempMat);rm.setForcedRenderState(renderState);vertexColorMaterial.render(quadGeom, rm);}public void enableClip(int x0, int y0, int x1, int y1) {clipWasSet = true;r.setClipRect(x0, getHeight() - y1, x1 - x0, y1 - y0);}public void disableClip() {if (clipWasSet) {r.clearClipRect();clipWasSet = false;}}}
  • 修改com.jme3.niftygui中的NiftyJmeDisplay.java文件,使其使用RenderDeviceAWT类,copy下面代码即可
/** Copyright (c) 2009-2012 jMonkeyEngine* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are* met:** * Redistributions of source code must retain the above copyright*   notice, this list of conditions and the following disclaimer.** * Redistributions in binary form must reproduce the above copyright*   notice, this list of conditions and the following disclaimer in the*   documentation and/or other materials provided with the distribution.** * Neither the name of 'jMonkeyEngine' nor the names of its contributors*   may be used to endorse or promote products derived from this software*   without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
package com.jme3.niftygui;import java.io.InputStream;
import java.net.URL;import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetManager;
import com.jme3.asset.AssetNotFoundException;
import com.jme3.audio.AudioRenderer;
import com.jme3.input.InputManager;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.post.SceneProcessor;
import com.jme3.profile.AppProfiler;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer;import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.render.batch.BatchRenderConfiguration;
import de.lessvoid.nifty.render.batch.BatchRenderDevice;
import de.lessvoid.nifty.tools.TimeProvider;
import de.lessvoid.nifty.tools.resourceloader.ResourceLocation;public class NiftyJmeDisplay implements SceneProcessor {protected boolean inited = false;protected Nifty nifty;protected AssetManager assetManager;protected RenderManager renderManager;protected InputManager inputManager;protected RenderDeviceAWT renderDev;protected JmeBatchRenderBackend batchRendererBackend;protected InputSystemJme inputSys;protected SoundDeviceJme soundDev;protected Renderer renderer;protected ViewPort vp;protected ResourceLocationJme resourceLocation;protected int w, h;private AppProfiler prof;protected class ResourceLocationJme implements ResourceLocation {public InputStream getResourceAsStream(String path) {AssetKey<Object> key = new AssetKey<Object>(path);AssetInfo info = assetManager.locateAsset(key);if (info != null) {return info.openStream();} else {throw new AssetNotFoundException(path);}}public URL getResource(String path) {throw new UnsupportedOperationException();}}//Empty constructor needed for jMP to create replacement input systempublic NiftyJmeDisplay() {}/*** Create a new NiftyJmeDisplay for use with the Batched Nifty Renderer.** Nifty will use texture atlases for rendering. Every graphical asset* you're rendering through Nifty will be placed into a texture atlas. The* goal is to render all Nifty components in a single (or at least very few)* draw calls. This should speed up rendering quite a bit.** This call will use a default BatchRenderConfiguration for Nifty.* See the other method {@link #newNiftyJmeDisplay(com.jme3.asset.AssetManager, com.jme3.input.InputManager, com.jme3.audio.AudioRenderer, com.jme3.renderer.ViewPort, de.lessvoid.nifty.render.batch.BatchRenderConfiguration) }* when you want to change the default BatchRenderConfiguration and provide* your own.** @param assetManager jME AssetManager* @param inputManager jME InputManager* @param audioRenderer jME AudioRenderer* @param viewport Viewport to use*/public static NiftyJmeDisplay newNiftyJmeDisplay(final AssetManager assetManager,final InputManager inputManager,final AudioRenderer audioRenderer,final ViewPort viewport) {return newNiftyJmeDisplay(assetManager,inputManager,audioRenderer,viewport,new BatchRenderConfiguration());}/*** Create a new NiftyJmeDisplay for use with the Batched Nifty Renderer.** Nifty will use texture atlas for rendering. Every graphical asset you're* rendering through Nifty will be placed into a texture atlas. The goal is* to render all Nifty components in a single (or at least very few) draw* calls. This should speed up rendering quite a bit.** @param assetManager jME AssetManager* @param inputManager jME InputManager* @param audioRenderer jME AudioRenderer* @param viewport Viewport to use* @param batchRenderConfiguration the Nifty BatchRenderConfiguration that*        you can use to further configure batch rendering. If unsure you*        can simply use new BatchRenderConfiguration() in here for the*        default configuration which should give you good default values.*/public static NiftyJmeDisplay newNiftyJmeDisplay(final AssetManager assetManager,final InputManager inputManager,final AudioRenderer audioRenderer,final ViewPort viewport,final BatchRenderConfiguration batchRenderConfiguration) {return new NiftyJmeDisplay(assetManager,inputManager,audioRenderer,viewport,batchRenderConfiguration);}/*** Create a new NiftyJmeDisplay for use with the Batched Nifty Renderer (improved Nifty rendering performance).** Nifty will use a single texture of the given dimensions (see atlasWidth and atlasHeight parameters). Every* graphical asset you're rendering through Nifty will be placed into this big texture. The goal is to render* all Nifty components in a single (or at least very few) draw calls. This should speed up rendering quite a* bit.** Currently you have to make sure to not use more image space than this single texture provides. However, Nifty* tries to be smart about this and internally will make sure that only the images are uploaded that your GUI* really needs. So in general this shoudln't be an issue.** A complete re-organisation of the texture atlas happens when a Nifty screen ends and another begins. Dynamically* adding images while a screen is running is supported as well.* * @param assetManager jME AssetManager* @param inputManager jME InputManager* @param audioRenderer jME AudioRenderer* @param viewport Viewport to use* @param atlasWidth the width of the texture atlas Nifty uses to speed up rendering (2048 is a good value)* @param atlasHeight the height of the texture atlas Nifty uses to speed up rendering (2048 is a good value)** @deprecated use the static factory methods {@link #newNiftyJmeDisplay(com.jme3.asset.AssetManager, com.jme3.input.InputManager, com.jme3.audio.AudioRenderer, com.jme3.renderer.ViewPort) }* or {@link #newNiftyJmeDisplay(com.jme3.asset.AssetManager, com.jme3.input.InputManager, com.jme3.audio.AudioRenderer, com.jme3.renderer.ViewPort, de.lessvoid.nifty.render.batch.BatchRenderConfiguration) }* instead of this constructor.*/public NiftyJmeDisplay(final AssetManager assetManager,final InputManager inputManager,final AudioRenderer audioRenderer,final ViewPort viewport,final int atlasWidth,final int atlasHeight) {// The code duplication in here really sucks - it's a copy of the// private constructor below that takes a BatchRenderConfiguration as an// additional parameter. This method should really be removed soon and// users should simply call the new factory methods.//// For now I keep this constructor as-is but have marked it as deprecated// to allow migration to the new way to instantiate this class.initialize(assetManager, inputManager, audioRenderer, viewport);this.renderDev = null;this.batchRendererBackend = new JmeBatchRenderBackend(this);BatchRenderConfiguration batchRenderConfiguration = new BatchRenderConfiguration();batchRenderConfiguration.atlasWidth = atlasWidth;batchRenderConfiguration.atlasHeight = atlasHeight;nifty = new Nifty(new BatchRenderDevice(batchRendererBackend, batchRenderConfiguration),soundDev,inputSys,new TimeProvider());inputSys.setNifty(nifty);resourceLocation = new ResourceLocationJme();nifty.getResourceLoader().removeAllResourceLocations();nifty.getResourceLoader().addResourceLocation(resourceLocation);}private NiftyJmeDisplay(final AssetManager assetManager,final InputManager inputManager,final AudioRenderer audioRenderer,final ViewPort viewport,final BatchRenderConfiguration batchRenderConfiguration) {initialize(assetManager, inputManager, audioRenderer, viewport);this.renderDev = null;this.batchRendererBackend = new JmeBatchRenderBackend(this);nifty = new Nifty(new BatchRenderDevice(batchRendererBackend, batchRenderConfiguration),soundDev,inputSys,new TimeProvider());inputSys.setNifty(nifty);resourceLocation = new ResourceLocationJme();nifty.getResourceLoader().removeAllResourceLocations();nifty.getResourceLoader().addResourceLocation(resourceLocation);}/*** Create a standard NiftyJmeDisplay. This uses the old Nifty renderer. It's probably slower then the batched* renderer and is mainly here for backwards compatibility.** @param assetManager jME AssetManager* @param inputManager jME InputManager* @param audioRenderer jME AudioRenderer* @param vp Viewport to use*/public NiftyJmeDisplay(AssetManager assetManager, InputManager inputManager,AudioRenderer audioRenderer,ViewPort vp){initialize(assetManager, inputManager, audioRenderer, vp);this.renderDev = new RenderDeviceAWT(this);this.batchRendererBackend = null;nifty = new Nifty(renderDev, soundDev, inputSys, new TimeProvider());inputSys.setNifty(nifty);resourceLocation = new ResourceLocationJme();nifty.getResourceLoader().removeAllResourceLocations();nifty.getResourceLoader().addResourceLocation(resourceLocation);}private void initialize(final AssetManager assetManager,final InputManager inputManager,final AudioRenderer audioRenderer,final ViewPort viewport) {this.assetManager = assetManager;this.inputManager = inputManager;this.w = viewport.getCamera().getWidth();this.h = viewport.getCamera().getHeight();this.soundDev = new SoundDeviceJme(assetManager, audioRenderer);this.inputSys = new InputSystemJme(inputManager);}public void initialize(RenderManager rm, ViewPort vp) {this.renderManager = rm;if (renderDev != null) {renderDev.setRenderManager(rm);} else {batchRendererBackend.setRenderManager(rm);}if (inputManager != null) {
//            inputSys.setInputManager(inputManager);inputManager.addRawInputListener(inputSys);}inited = true;this.vp = vp;this.renderer = rm.getRenderer();inputSys.reset();inputSys.setHeight(vp.getCamera().getHeight());}public Nifty getNifty() {return nifty;}public void simulateKeyEvent( KeyInputEvent event ) {inputSys.onKeyEvent(event);        }AssetManager getAssetManager() {return assetManager;}RenderManager getRenderManager() {return renderManager;}int getHeight() {return h;}int getWidth() {return w;}Renderer getRenderer(){return renderer;}public void reshape(ViewPort vp, int w, int h) {this.w = w;this.h = h;inputSys.setHeight(h);nifty.resolutionChanged();}public boolean isInitialized() {return inited;}public void preFrame(float tpf) {}public void postQueue(RenderQueue rq) {// render nifty before anything elserenderManager.setCamera(vp.getCamera(), true);//nifty.update();nifty.render(false);renderManager.setCamera(vp.getCamera(), false);}public void postFrame(FrameBuffer out) {}public void cleanup() {inited = false;inputSys.reset();if (inputManager != null) {inputManager.removeRawInputListener(inputSys);}}@Overridepublic void setProfiler(AppProfiler profiler) {this.prof = profiler;}}
打包

用gradle将改动的包build,然后把jar替换到项目里即可

同理找到jme3-niftygui的gradle,build并替换就可以在gui及项目中使用中文了。

03 Jme3和Nifty1.4.2中文显示相关推荐

  1. jsp 中提交表单后在firefox、chrome 中中文显示为正常,但在IE中中文显示为乱码?...

    如题: jsp 中提交表单后在firefox.chrome 中中文显示为正常,但在IE中中文显示为乱码? 备注:框架:spring 和hibernate 提交表单后,在IE中提交的数据传到Contro ...

  2. Xna支持中文显示方法归纳

    Xna不同于DirectX,因其内部并未提供类似于D3DFont的机制(据说之所以会这样做,也是考虑到与Xbox360兼容的缘故),使得显示中文变得极为不便. 虽然如此,要实现Xna下的中文显示依然存 ...

  3. 编码影响页面的渲染:utf-8下的Arial字体中文显示

    先拿搜索引擎:百度跟bing比较         中文的显示样式明显不一样,我们通常会使用Arial字体作为第一通用字体,百度跟bing也一样,为何中文显示就有这么大差距呢? 我在开发过程中也碰到这个 ...

  4. 只需4步,让OKA40i-C开发板的Linux系统拥有中文显示

    如果你试着在Linux系统里面输入中文,那么将会有一片乱码呈现在你面前,这是因为Linux系统的默认语言是英文.但是如果可以显示中文的话,那么在使用过程中的便利程度一定会大大提升.今天小编就通过飞凌嵌 ...

  5. python汉字无法显示图片_完美解决matplotlib画图中文显示问题

    相信有很多人曾经被matplotlib画图的中文显示问题所困扰,包括我自己.每次生产环境发生改变,都会遭遇到这个问题,然后需要花大量的时间在它上边.最可气的是每次遇到的问题不一定一样,上一次使用的方法 ...

  6. mysql表中的中文是乱码_mysql插入表中的中文显示为乱码或问号的解决方法

    版权声明:本文为博主原创文章,未经博主允许不得转载. 今天在做ssh的博客项目时发现mysql数据库中的中文显示为问号,网上查阅了很多资料,都不是很全,所以我总结一下,供大家参考和自己复习. 1.我的 ...

  7. python 读取excel 内的中文显示为unicode 编码

    测试的excel 显示如下 读取excel 打印的效果如下 现在想显示为中文 处理代码如下 #!/usr/bin/python# # -*- coding: utf-8 -*- import xlrd ...

  8. PL/SQL 中文显示乱码解决方案

    为什么80%的码农都做不了架构师?>>>    PL/SQL 中文显示乱码: 1.修改注册表进行设置: HKEY_LOCAL_MACHINE->SOFTWARE->ORA ...

  9. oracle11g怎么显示中文,ORACLE11G中PLSQL中文显示乱码、Linux下sqlplus查询中文乱码

    问题描述: 本地是win7操作系统,cmd里面sqlplus进去连接oracle数据库,中文可以正常显示,但是plsql连接oracle数据库,中文显示乱码,还有xshell远程连接oracle服务器 ...

最新文章

  1. windows共享linux的某一文件夹
  2. Linux系统上传文件与下载文件命令
  3. android 观察者的框架,Android 架构师7 设计模式之观察者模式
  4. 《Unix网络编程》环境搭建
  5. Verilog 三段式状态机(转)
  6. Scrapy 爬取链家租房价格信息
  7. 【汽车总线技术】PCAN-Diag FD简介及其应用 ——手持式CAN/CAN FD总线诊断设备
  8. 10min说完淘宝最初10年的产品故事
  9. 抖音实战~手机号一键注册登录流程(验证码)
  10. 真正的人工智能,需要理解本体论
  11. django笔记10 cookie整理
  12. Java程序员的春天!java第三方线程池
  13. 你喜欢哪款 Linux 桌面?萝莉风?御姐风?
  14. oracle表数据恢复为1小时之前,恢复一个小时前数据
  15. 超详细的单摄→双摄→三摄→3D成像摄像头产业链
  16. 自动ip的计算机共享打印,局域网内自动获取ip地址怎么设置打印机共享文件夹...
  17. [Python]小甲鱼Python视频第023~024课(递归:这帮小兔崽子、汉诺塔)课后题及参考解答...
  18. 北京交通大学计算机学院考研,2019北京交通大学计算机考研考生科目、参考书目、招生人数...
  19. Python 歌手得分计算程序
  20. 北京尚学堂|为什么要学习Java

热门文章

  1. 微信PC端不显示头像和表情怎么解决
  2. MODIS 产品介绍
  3. 90后歌单精选100首,我有歌,你有故事吗?
  4. 转:Windows Shell 编程 第七章_1
  5. 半年经验Java面试准备
  6. Mac苹果电脑开不了机怎么办,该怎么修复
  7. crypto-music is frequency(INS‘hAck CTF 2018)
  8. 秋天NET快速强签名工具V1.1
  9. 【BZOJ1503】郁闷的出纳员
  10. 最新-手把手教Unity2017.3 Android Studio3.0.1 SDK接入教程含jdk和sdk环境配置