/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package GUI;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.image.ImageRaster;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.core.GuiMaterial;
import com.simsilica.lemur.core.VersionedReference;
import java.nio.FloatBuffer;
/**
* 裁剪处理UI的PNG图像
* @author Icyboxs
*/
public final class LemurQuadBackgroundComponentEnhanced extends QuadBackgroundComponent{
private Geometry background;
private ColorRGBA color;
private float alpha = 1f;
private Texture texture;
private Vector2f textureCoordinateScale;
private GuiMaterial material;
private float xMargin = 0;
private float yMargin = 0;
private float zOffset = 0.01f;
private float alphaDiscard = 0;
private boolean lit = false;
private Vector2f tiling= new Vector2f();
private Vector2f offset= new Vector2f();
private Vector2f Resolution= new Vector2f();
private imgResolutionData resolutionData = new imgResolutionData(); // 初始化 resolutionData;
private Vector2f appliedTextureScale = new Vector2f(1, 1);
public LemurQuadBackgroundComponentEnhanced() {
this(ColorRGBA.Gray, 0, 0, 0.01f, false);
}
public LemurQuadBackgroundComponentEnhanced( ColorRGBA color ) {
this(color, 0, 0, 0.01f, false);
}
public LemurQuadBackgroundComponentEnhanced( ColorRGBA color, float xMargin, float yMargin ) {
this(color, xMargin, yMargin, 0.01f, false);
}
public LemurQuadBackgroundComponentEnhanced( ColorRGBA color,
float xMargin, float yMargin, float zOffset,
boolean lit ) {
this.xMargin = xMargin;
this.yMargin = yMargin;
this.zOffset = zOffset;
this.lit = lit;
setColor(color);
createMaterial();
}
public LemurQuadBackgroundComponentEnhanced( Texture texture ) {
this(texture, 0, 0, 0.01f, false);
}
public LemurQuadBackgroundComponentEnhanced( Texture texture, float xMargin, float yMargin ) {
this(texture, xMargin, yMargin, 0.01f, false);
}
public LemurQuadBackgroundComponentEnhanced( Texture texture,
float xMargin, float yMargin, float zOffset,
boolean lit ) {
this.xMargin = xMargin;
this.yMargin = yMargin;
this.zOffset = zOffset;
this.lit = lit;
setTexture(texture);
setColor(ColorRGBA.White);
createMaterial();
}
public LemurQuadBackgroundComponentEnhanced( Texture texture,
float xMargin, float yMargin, float zOffset,
boolean lit,
int xResolution,int yResolution,
int xCropResolution,int yCropResolution,
int xOffsetResolution,int yOffsetResolution) {
this.resolutionData.setxResolution(xResolution);
this.resolutionData.setyResolution(yResolution);
this.resolutionData.setxCropResolution(xCropResolution);
this.resolutionData.setyCropResolution(yCropResolution);
this.resolutionData.setxOffsetResolution(xOffsetResolution);
this.resolutionData.setyOffsetResolution(yOffsetResolution);
this.xMargin = xMargin;
this.yMargin = yMargin;
this.zOffset = zOffset;
this.lit = lit;
setTexture(texture);
setColor(ColorRGBA.White);
createMaterial();
}
public LemurQuadBackgroundComponentEnhanced( Texture texture,
float xMargin, float yMargin, float zOffset,
boolean lit ,imgResolutionData IRD) {
this.resolutionData=IRD;
this.xMargin = xMargin;
this.yMargin = yMargin;
this.zOffset = zOffset;
this.lit = lit;
setTexture(texture);
setColor(ColorRGBA.White);
createMaterial();
}
@Override
protected void refreshBackground( Vector3f size ) {
if( background == null ) {
Quad q = new Quad(size.x, size.y);
if( lit ) {
// Give the quad some normals
q.setBuffer(VertexBuffer.Type.Normal, 3,
new float[] {
0, 0, 1,
0, 0, 1,
0, 0, 1,
0, 0, 1
});
}
background = new Geometry("background", q);
// Can't do this even though it seems logical because it
// is just as likely that we are in bucket.gui. It is up to
// the caller to put the main 3D ui in the transparent bucket
//background.setQueueBucket(Bucket.Transparent);
if( material == null ) {
createMaterial();
}
background.setMaterial(material.getMaterial());
refreshMesh(background,resolutionData);
getNode().attachChild(background);
// If we've recreated the spatial then the applied scale
// should be reset also. We could either move slightly different
// scaling logic into the branch and the else branch... or just
// reset appliedTextureScale here so that the if branch below
// rescales things properly.
appliedTextureScale.set(1, 1);
} else {
// Else reset the size of the quad
Quad q = (Quad)background.getMesh();
if( size.x != q.getWidth() || size.y != q.getHeight() ) {
q.updateGeometry(size.x, size.y);
q.clearCollisionData();
}
}
Vector2f effectiveScale = textureCoordinateScale == null ? Vector2f.UNIT_XY : textureCoordinateScale;
if( !appliedTextureScale.equals(effectiveScale) ) {
// Need to apply new texture coordinate scaling
Mesh m = background.getMesh();
// Unscale what we already scaled
m.scaleTextureCoordinates(new Vector2f(1/appliedTextureScale.x, 1/appliedTextureScale.y));
appliedTextureScale.set(effectiveScale);
// And now apply the latest coordinate scaling.
m.scaleTextureCoordinates(appliedTextureScale);
// Note: it's probably safer to have just applied the scale value directly to
// the quad's texture coordinate values instead of multiplying. The above may
// accumulate errors. Still, I thought this would be more future proof and
// transferable to other things since it works with any mesh and not just quads.
}
}
private void refreshMesh(Geometry geom,imgResolutionData resolutionData) {
this.tiling.x=resolutionData.getxCropResolution()/resolutionData.getxResolution();
this.tiling.y=resolutionData.getyCropResolution()/resolutionData.getyResolution();
this.offset.x=resolutionData.getxOffsetResolution()/resolutionData.getxResolution();
this.offset.y=resolutionData.getyOffsetResolution()/resolutionData.getyResolution();
Quad mesh = (Quad) geom.getMesh();
VertexBuffer tc = mesh.getBuffer(VertexBuffer.Type.TexCoord);
float[] uv = new float[]{
0, 0,
1, 0,
1, 1,
0, 1};
FloatBuffer fb = (FloatBuffer) tc.getData();
fb.clear();
for (int i = 0; i < uv.length; i += 2) {
System.err.println("L:"+i);
float x = uv[i];
float y = uv[i + 1];
x = x * tiling.getX() + offset.getX();
y = y * tiling.getY() + offset.getY();
fb.put(x).put(y);
}
fb.clear();
tc.updateData(fb);
}
public void setimgResolutionData(int xResolution,int yResolution,int xCropResolution,int yCropResolution,int xOffsetResolution,int yOffsetResolution) {
this.resolutionData.setxResolution(xResolution);
this.resolutionData.setyResolution(yResolution);
this.resolutionData.setxCropResolution(xCropResolution);
this.resolutionData.setyCropResolution(yCropResolution);
this.resolutionData.setxOffsetResolution(xOffsetResolution);
this.resolutionData.setyOffsetResolution(yOffsetResolution);
}
@Override
protected void createMaterial() {
material = GuiGlobals.getInstance().createMaterial(color, lit);
if( texture != null ) {
material.setTexture(texture);
}
material.getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
material.getMaterial().setFloat("AlphaDiscardThreshold", alphaDiscard);
}
@Override
public QuadBackgroundComponent clone() {
LemurQuadBackgroundComponentEnhanced result = (LemurQuadBackgroundComponentEnhanced)super.clone();
result.material = material.clone();
result.background = null;
return result;
}
}
import com.simsilica.lemur.*;
import com.simsilica.lemur.Button.ButtonAction;
import com.simsilica.lemur.component.*;
import GUI.*;
def gradient = TbtQuadBackgroundComponent.create(
texture( name:"/com/simsilica/lemur/icons/bordered-gradient.png",
generateMips:false ),
1, 1, 1, 126, 126,
1f, false );
def bevel = TbtQuadBackgroundComponent.create(
texture( name:"/com/simsilica/lemur/icons/bevel-quad.png",
generateMips:false ),
0.125f, 8, 8, 119, 119,
1f, false );
def border = TbtQuadBackgroundComponent.create(
texture( name:"/com/simsilica/lemur/icons/border.png",
generateMips:false ),
1, 1, 1, 6, 6,
1f, false );
def border2 = TbtQuadBackgroundComponent.create(
texture( name:"/com/simsilica/lemur/icons/border.png",
generateMips:false ),
1, 2, 2, 6, 6,
1f, false );
def doubleGradient = new QuadBackgroundComponent( color(0.5, 0.75, 0.85, 0.5) );
doubleGradient.texture = texture( name:"/com/simsilica/lemur/icons/double-gradient-128.png",
generateMips:false )
selector( "myglass" ) {
fontSize = 14
}
selector( "label", "myglass" ) {
insets = new Insets3f( 2, 2, 0, 2 );
color = color(0.5, 0.75, 0.75, 0.85)
}
selector( "container", "myglass" ) {
background = gradient.clone()
background.setColor(color(0.25, 0.5, 0.5, 0.5))
}
selector( "slider", "myglass" ) {
background = gradient.clone()
background.setColor(color(0.25, 0.5, 0.5, 0.5))
}
def pressedCommand = new Command<Button>() {
public void execute( Button source ) {
if( source.isPressed() ) {
source.move(1, -1, 0);
} else {
source.move(-1, 1, 0);
}
}
};
def repeatCommand = new Command<Button>() {
private long startTime;
private long lastClick;
public void execute( Button source ) {
// Only do the repeating click while the mouse is
// over the button (and pressed of course)
if( source.isPressed() && source.isHighlightOn() ) {
long elapsedTime = System.currentTimeMillis() - startTime;
// After half a second pause, click 8 times a second
if( elapsedTime > 500 ) {
if( elapsedTime - lastClick > 125 ) {
source.click();
// Try to quantize the last click time to prevent drift
lastClick = ((elapsedTime - 500) / 125) * 125 + 500;
}
}
} else {
startTime = System.currentTimeMillis();
lastClick = 0;
}
}
};
def stdButtonCommands = [
(ButtonAction.Down):[pressedCommand],
(ButtonAction.Up):[pressedCommand]
];
def sliderButtonCommands = [
(ButtonAction.Hover):[repeatCommand]
];
selector( "title", "myglass" ) {
color = color(0.8, 0.9, 1, 0.85f)
highlightColor = color(1, 0.8, 1, 0.85f)
shadowColor = color(0, 0, 0, 0.75f)
shadowOffset = new com.jme3.math.Vector3f(2, -2, -1);
background = new QuadBackgroundComponent( color(0.5, 0.75, 0.85, 0.5) );
background.texture = texture( name:"/com/simsilica/lemur/icons/double-gradient-128.png",
generateMips:false )
insets = new Insets3f( 2, 2, 2, 2 );
buttonCommands = stdButtonCommands;
}
selector( "button", "myglass" ) {
background = new LemurQuadBackgroundComponentEnhanced( color(0.5, 0.75, 0.85, 0.5) );
background.texture = texture( name:"/Textures/UI/Steampunk_UI_Alternative_Colors_1.png",
generateMips:false )
background.setimgResolutionData(1920,1080,574,230,28,551)
color = color(0.8, 0.9, 1, 0.85f)
background.setColor(color(0, 0.75, 0.75, 0.5))
insets = new Insets3f( 2, 2, 2, 2 );
buttonCommands = stdButtonCommands;
}
selector( "slider", "myglass" ) {
insets = new Insets3f( 1, 3, 1, 2 );
}
selector( "slider", "button", "myglass" ) {
background = doubleGradient.clone()
background.setColor(color(0.5, 0.75, 0.75, 0.5))
insets = new Insets3f( 0, 0, 0, 0 );
}
selector( "slider.thumb.button", "myglass" ) {
text = "[]"
color = color(0.6, 0.8, 0.8, 0.85)
}
selector( "slider.left.button", "myglass" ) {
text = "-"
background = doubleGradient.clone()
background.setColor(color(0.5, 0.75, 0.75, 0.5))
background.setMargin(5, 0);
color = color(0.6, 0.8, 0.8, 0.85)
buttonCommands = sliderButtonCommands;
}
selector( "slider.right.button", "myglass" ) {
text = "+"
background = doubleGradient.clone()
background.setColor(color(0.5, 0.75, 0.75, 0.5))
background.setMargin(4, 0);
color = color(0.6, 0.8, 0.8, 0.85)
buttonCommands = sliderButtonCommands;
}
selector( "slider.up.button", "myglass" ) {
buttonCommands = sliderButtonCommands;
}
selector( "slider.down.button", "myglass" ) {
buttonCommands = sliderButtonCommands;
}
selector( "checkbox", "myglass" ) {
def on = new IconComponent( "/com/simsilica/lemur/icons/Glass-check-on.png", 1f,
0, 0, 1f, false );
on.setColor(color(0.5, 0.9, 0.9, 0.9))
on.setMargin(5, 0);
def off = new IconComponent( "/com/simsilica/lemur/icons/Glass-check-off.png", 1f,
0, 0, 1f, false );
off.setColor(color(0.6, 0.8, 0.8, 0.8))
off.setMargin(5, 0);
onView = on;
offView = off;
color = color(0.8, 0.9, 1, 0.85f)
}
selector( "rollup", "myglass" ) {
background = gradient.clone()
background.setColor(color(0.25, 0.5, 0.5, 0.5))
}
selector( "tabbedPanel", "myglass" ) {
activationColor = color(0.8, 0.9, 1, 0.85f)
}
selector( "tabbedPanel.container", "myglass" ) {
background = null
}
selector( "tab.button", "myglass" ) {
background = gradient.clone()
background.setColor(color(0.25, 0.5, 0.5, 0.5))
color = color(0.4, 0.45, 0.5, 0.85f)
insets = new Insets3f( 4, 2, 0, 2 );
buttonCommands = stdButtonCommands;
}
严重: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.NullPointerException: Cannot invoke "com.simsilica.lemur.core.GuiMaterial.clone()" because "this.material" is null
at com.simsilica.lemur.component.QuadBackgroundComponent.clone(QuadBackgroundComponent.java:117)
at GUI.LemurQuadBackgroundComponentEnhanced.clone(LemurQuadBackgroundComponentEnhanced.java:249)
at GUI.LemurQuadBackgroundComponentEnhanced.clone(LemurQuadBackgroundComponentEnhanced.java:30)
at com.simsilica.lemur.style.Styles.clone(Styles.java:520)
at com.simsilica.lemur.style.Styles.applyStyles(Styles.java:470)
at com.simsilica.lemur.Button.<init>(Button.java:129)
at com.simsilica.lemur.Button.<init>(Button.java:105)
at GUI.UI.onEnable(UI.java:86)
at com.jme3.app.state.BaseAppState.initialize(BaseAppState.java:132)
at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:332)
at com.jme3.app.state.AppStateManager.update(AppStateManager.java:362)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:258)
at com.jme3.system.lwjgl.LwjglWindow.runLoop(LwjglWindow.java:628)
at com.jme3.system.lwjgl.LwjglWindow.run(LwjglWindow.java:717)
at java.base/java.lang.Thread.run(Thread.java:833)
·Cannot invoke “com.simsilica.lemur.core.GuiMaterial.clone()” because “this.material” is null·
I don’t quite understand why this value is empty.