Hello,
I’m struggling doing a rather simple task - I want to draw just a portion of a given image and not the entire image. I’m using this code:
Texture2D tex = (Texture2D)assetManager.loadTexture(resource.path);
pic = new Picture(cmd.resourceName+"_"+_drawChannels.size());
pic.setTexture(assetManager, tex, true);
// pic.setWidth(settings.getWidth()/2);
// pic.setHeight(settings.getHeight()/2);
guiNode.attachChild(pic);
And I’m ;looking for methods either in the Texture2D or in the Picture for selecting the desired portion of the image something like getting the : X,Y,Width,Height of the raw image.
Must be a way…
WDYT?
Well, here is what we do in similar situations, in case it gives you some inspiration:
/* * Copyright (C) 2014-2019 OpenKeeper * * OpenKeeper is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenKeeper is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenKeeper. If not, see <http://www.gnu.org/licenses/>. */ package toniarts.openkeeper.gui.nifty.jme; import com.jme3.app.SimpleApplication; import com.jme3.asset.AssetManager; import com.jme3.asset.TextureKey; import com.jme3.texture.Texture2D; import de.lessvoid.nifty.Nifty; import de.lessvoid.nifty.controls.Parameters; import de.lessvoid.nifty.elements.Element; import de.lessvoid.nifty.screen.Screen; import java.awt.Color; /** * Draws a kinda progress effect image on top of a Nifty element * * @author Toni Helenius <helenius.toni@gmail.com> */ public class ResearchEffectControl extends AbstractNiftyJmeControl { public static final String CONTROL_NAME = "researchEffect"; private ProgressIndicatorPicture picture; private boolean initialized = false; private float research = 0; private Color color; private String image; @Override public void bind(Nifty nifty, Screen screen, Element element, Parameters parameter) { super.bind(nifty, screen, element, parameter); String colorString = parameter.get("color"); if (colorString != null && !"".equals(colorString)) { color = new Color(Integer.parseInt(colorString), true); } image = parameter.getWithDefault("image", ""); if ("".equals(image)) { image = null; } // Sanity check if (color == null && image == null) { throw new IllegalArgumentException("Need to specify either color or image!"); } } @Override public void initJme(SimpleApplication app) { super.initJme(app); picture = new ProgressIndicatorPicture("ResearchIndicator"); picture.setHeight(getControlHeight()); picture.setWidth(getControlWidth()); picture.setPosition(getControlX(), getControlY()); picture.addControl(new SimpleJmeControl(this)); } @Override protected void cleanup() { if (initialized) { getApp().getGuiNode().detachChild(picture); } } public void setResearch(float research) { this.research = research; if (!initialized && research > 0) { initialize(); } else { picture.setProgress(getApp().getAssetManager(), research); } } private void initialize() { initialized = true; AssetManager assetManager = getApp().getAssetManager(); // Make sure we are drawing on the right spot picture.setHeight(getControlHeight()); picture.setWidth(getControlWidth()); picture.setPosition(getControlX(), getControlY()); picture.setProgress(assetManager, research); // Set the color or the picture if (image != null) { TextureKey key = new TextureKey(image, true); Texture2D tex = (Texture2D) assetManager.loadTexture(key); picture.setTexture(assetManager, tex, true); } else { picture.setColor(assetManager, color, true); } // Attach to scene getApp().getGuiNode().attachChild(picture); } }
1 Like
You probably want to create a quad with some different texture coordinates than just the four corners of the image.
Check out @ndebruyn ’s galago framework, most importantly the sprite class:
Galago2D/Sprite.java at master · nickidebruyn/Galago2D · GitHub
1 Like
Thanks! I have updated the code and it works fine except that I don’t have transparency in the rendered image. here is the code:
public void channelDraw(ChannelDrawCommand cmd) {
Picture pic = _drawChannels.get(cmd.resourceName);
String fromRes=cmd.resourceName;
ResourceSetup2D resource = assetsMapping.getSpriteSheetsIndex().get(fromRes.toLowerCase());
if(resource==null){
return ;
}
if(pic==null) {
BufferedImage img = null;
try {
img = ImageIO.read(assetManager.locateAsset(new AssetKey(resource.path)).openStream());
} catch (IOException ex) {
//LOGGER.log(Level.SEVERE, "Failed to load the backdrop image with " + image + "!", ex);
}
int width = img.getWidth()/resource.cols;
int height = img.getHeight()/resource.rows;
int startX = 0;
int startY=0;
BufferedImage newImage = new BufferedImage(width, height, img != null ? img.getType() : BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(img,0,0,width,height,startX,startY,startX+width,startY+height, Color.MAGENTA,null);
AWTLoader loader = new AWTLoader();
Texture2D tex = new Texture2D(loader.load(newImage, true));
pic = new Picture(cmd.resourceName+"_"+_drawChannels.size());
pic.setTexture(assetManager, tex, true);
pic.getMaterial().getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
pic.getMaterial().setTransparent(true);
pic.setWidth(width);
pic.setHeight(height);
guiNode.attachChild(pic);
} else {
pic.setImage(assetManager, resource.path, true);
}
pic.setPosition(cmd.posXVal, settings.getHeight() - pic.getLocalScale().getY() - cmd.posYVal);
}
What is missing in order to make it draw with transparency?
OK, found it. needed to put null in the bgcolor:
g.drawImage(img,0,0,width,height,startX,startY,startX+width,startY+height, null,null);
Now it’s finally working as expected
pspeed
July 19, 2020, 7:46pm
6
If you ever decide that you don’t want to make a whole separate image + texture just to render part of a texture you’ve already loaded… then the texture coordinate answer is the right one and only takes one line of code.
3 Likes
I see future potential in the Graphics2D drawing methods so for now I’ll keep it
Yep, if you don’t need to modify the texture in any way, just shift it, the texture coordinates are probably way faster.
In our use case as well, using some shader trick to draw the texture partly (the arc thing) would have been much better and faster. But since I can’t yet handle those, Graphics2D is an hacky option.
1 Like