diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index a783f1f9674..01e97ec9242 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Matrix4; @@ -37,8 +38,75 @@ public class Graphics { private int failedClipCount; private float alphaComposite = 1; private int transformCount = 0; + private String sVertex = "uniform mat4 u_projTrans;\n" + + "\n" + + "attribute vec4 a_position;\n" + + "attribute vec2 a_texCoord0;\n" + + "attribute vec4 a_color;\n" + + "\n" + + "varying vec4 v_color;\n" + + "varying vec2 v_texCoord;\n" + + "\n" + + "uniform vec2 u_viewportInverse;\n" + + "\n" + + "void main() {\n" + + " gl_Position = u_projTrans * a_position;\n" + + " v_texCoord = a_texCoord0;\n" + + " v_color = a_color;\n" + + "}"; + private String sFragment = "#ifdef GL_ES\n" + + "precision mediump float;\n" + + "precision mediump int;\n" + + "#endif\n" + + "\n" + + "uniform sampler2D u_texture;\n" + + "\n" + + "// The inverse of the viewport dimensions along X and Y\n" + + "uniform vec2 u_viewportInverse;\n" + + "\n" + + "// Color of the outline\n" + + "uniform vec3 u_color;\n" + + "\n" + + "// Thickness of the outline\n" + + "uniform float u_offset;\n" + + "\n" + + "// Step to check for neighbors\n" + + "uniform float u_step;\n" + + "\n" + + "varying vec4 v_color;\n" + + "varying vec2 v_texCoord;\n" + + "\n" + + "#define ALPHA_VALUE_BORDER 0.5\n" + + "\n" + + "void main() {\n" + + " vec2 T = v_texCoord.xy;\n" + + "\n" + + " float alpha = 0.0;\n" + + " bool allin = true;\n" + + " for( float ix = -u_offset; ix < u_offset; ix += u_step )\n" + + " {\n" + + " for( float iy = -u_offset; iy < u_offset; iy += u_step )\n" + + " {\n" + + " float newAlpha = texture2D(u_texture, T + vec2(ix, iy) * u_viewportInverse).a;\n" + + " allin = allin && newAlpha > ALPHA_VALUE_BORDER;\n" + + " if (newAlpha > ALPHA_VALUE_BORDER && newAlpha >= alpha)\n" + + " {\n" + + " alpha = newAlpha;\n" + + " }\n" + + " }\n" + + " }\n" + + " if (allin)\n" + + " {\n" + + " alpha = 0.0;\n" + + " }\n" + + "\n" + + " gl_FragColor = vec4(u_color,alpha);\n" + + "}"; + + private final ShaderProgram shaderOutline = new ShaderProgram(sVertex, sFragment); public Graphics() { + ShaderProgram.pedantic = false; } public void begin(float regionWidth0, float regionHeight0) { @@ -604,6 +672,56 @@ public class Graphics { public void drawImage(TextureRegion image, float x, float y, float w, float h) { batch.draw(image, adjustX(x), adjustY(y, h), w, h); } + public void drawImage(TextureRegion image, TextureRegion glowImageReference, float x, float y, float w, float h, Color glowColor, boolean selected) { + //1st image is the image on top of the shader, 2nd image is for the outline reference for the shader glow... + // if the 1st image don't have transparency in the middle (only on the sides, top and bottom, use the 1st image as outline reference... + if (!selected) { + batch.draw(image, adjustX(x), adjustY(y, h), w, h); + } else { + batch.end(); + shaderOutline.begin(); + shaderOutline.setUniformf("u_viewportInverse", new Vector2(1f / w, 1f / h)); + shaderOutline.setUniformf("u_offset", 3f); + shaderOutline.setUniformf("u_step", Math.min(1f, w / 70f)); + shaderOutline.setUniformf("u_color", new Vector3(glowColor.r, glowColor.g, glowColor.b)); + shaderOutline.end(); + batch.setShader(shaderOutline); + batch.begin(); + //glow + batch.draw(glowImageReference, adjustX(x), adjustY(y, h), w, h); + batch.end(); + batch.setShader(null); + batch.begin(); + //img + batch.draw(image, adjustX(x), adjustY(y, h), w, h); + } + } + public void drawDeckBox(FImage cardArt, float scale, TextureRegion image, TextureRegion glowImageReference, float x, float y, float w, float h, Color glowColor, boolean selected) { + float yBox = y-(h*0.25f); + if (!selected) { + cardArt.draw(this,x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f); + batch.draw(image, adjustX(x), adjustY(yBox, h), w, h); + } else { + batch.end(); + shaderOutline.begin(); + shaderOutline.setUniformf("u_viewportInverse", new Vector2(1f / w, 1f / h)); + shaderOutline.setUniformf("u_offset", 3f); + shaderOutline.setUniformf("u_step", Math.min(1f, w / 70f)); + shaderOutline.setUniformf("u_color", new Vector3(glowColor.r, glowColor.g, glowColor.b)); + shaderOutline.end(); + batch.setShader(shaderOutline); + batch.begin(); + //glow + batch.draw(glowImageReference, adjustX(x), adjustY(yBox, h), w, h); + batch.end(); + batch.setShader(null); + batch.begin(); + //cardart + cardArt.draw(this,x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f); + //deckbox + batch.draw(image, adjustX(x), adjustY(yBox, h), w, h); + } + } public void drawRepeatingImage(Texture image, float x, float y, float w, float h) { if (startClip(x, y, w, h)) { //only render if clip successful, otherwise it will escape bounds diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java index cb8208e27f1..064425773bc 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java @@ -989,14 +989,14 @@ public class ImageView extends ItemView { float scale = 0.75f; if (dpImg != null) {//generated decks have missing info... - if (selected) - g.fillRoundRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE, (h - w) / 10); if (Forge.enableUIMask){ //commander bg - g.drawImage(FSkin.getDeckbox().get(0),x, y, w, h); + g.drawImage(FSkin.getDeckbox().get(0), FSkin.getDeckbox().get(0), x, y, w, h, Color.GREEN, selected); TextureRegion tr = ImageCache.croppedBorderImage(dpImg); g.drawImage(tr, x+(w-w*scale)/2, y+(h-h*scale)/1.5f, w*scale, h*scale); } else { + if (selected) + g.fillRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE); g.drawImage(dpImg, x, y, w, h); } //fake labelname shadow @@ -1006,19 +1006,13 @@ public class ImageView extends ItemView { } else { if (!dp.isGeneratedDeck()){ FImageComplex cardArt = CardRenderer.getCardArt(dp.getHighestCMCCard().getImageKey(false), false, false, false); - //after getting cardArt we draw the selector first if selected here in deckSelectMode, we don't want to draw the selection before getting the cardArt - if (selected) - g.fillRoundRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 2 * SEL_BORDER_SIZE, w + 12 * SEL_BORDER_SIZE, (h - w) / 10); //draw the deckbox if (cardArt != null){ - //card art - cardArt.draw(g, x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f); - //deck box - g.drawImage(FSkin.getDeckbox().get(1),x, y-(h*0.25f), w, h); + g.drawDeckBox(cardArt, scale, FSkin.getDeckbox().get(1), FSkin.getDeckbox().get(2), x, y, w, h, Color.GREEN, selected); } } else { //generic box - g.drawImage(FSkin.getDeckbox().get(2),x, y-(h*0.25f), w, h); + g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y-(h*0.25f), w, h, Color.GREEN, selected); } if (deckColor != null) { //deck color identity diff --git a/forge-gui/res/skins/default/sprite_deckbox.png b/forge-gui/res/skins/default/sprite_deckbox.png index 3257bef98d9..104d2018f0e 100644 Binary files a/forge-gui/res/skins/default/sprite_deckbox.png and b/forge-gui/res/skins/default/sprite_deckbox.png differ