Image Painter Plugin Available

Zero Separation is pleased to release ImagePainter as a jME3 SDK plugin.



ImagePainter has now been converted to use ImageRaster and released as an SDK plugin. The actual plugin-making progress was pretty smooth and clearly explained so kudos to the team members for that.



For those who don’t know ImagePainter provides a reasonably comprehensive set of painting tools for modifying jME3 Images (or anything else that can be wrapped by an ImageRaster). This includes painting ImageRasters into other ImageRasters (complete with scaling, rotation, opacity, 9-patch-style, etc) and painting of Text in both single and multiple lines and automatically scaling text to fit into an available area. The paint process even includes Blend modes similar to Photoshop’s layer modes!



To use the new plugin simply update to the latest Nightly release (it isn’t in stable yet but will be at some point).



Go to tools-plugins and find Image Painter under available plugins. Add that plugin to your SDK.



Now in your project go to the Libraries folder, open a menu and select Add Library and then add the new Image Painter library which should now be visible.



The new library has full javadoc so should be straightforward to use. Some examples from testing follow:



http://www.youtube.com/watch?v=l_1PvEeHw98&t=7m42s









For more examples ImagePainter is what is used to create the Cards in Zero-Separation's game HeroDex (http://www.herodex.net). They are most easily seen in the Card List at http://www.herodex.net/cards/index.php.
12 Likes

We got there in the end :wink: Thanks for going the extra mile zarch, your attitude has been rather exemplary.

1 Like

Yeah this is cool, now all people asking for this can get it with a click of a button or by downloading a jar from svn if they choose so :wink:

1 Like

Yes, I’m definitely liking the plugin system. It’s a very smart way to distribute optional content like this.



How many people have actually tried it so far? Is it going smoothly for everyone?



Out of interest does jME3 keep any metrics on the plugins people have installed? It would be interesting to know how many people are using what although I can see how there might be privacy issues if it got too intrusive.

1 Like
@zarch said:
Yes, I'm definitely liking the plugin system. It's a very smart way to distribute optional content like this.
Couldn't agree more. The forum restructuring definitely helped put some focus on it, and I tried emphasizing plugins in my last contributor announcement as well, but "Plugins" could still benefit from more attention. Probably a blog post dedicated to plugins and a more prominent link somewhere would go a long way. We've also long been playing with the idea of a web-based frontend to the plugins repository, akin to http://plugins.netbeans.org/

How many people have actually tried it so far? Is it going smoothly for everyone?

Out of interest does jME3 keep any metrics on the plugins people have installed? It would be interesting to know how many people are using what although I can see how there might be privacy issues if it got too intrusive.

It seems to be going smoother at least. Normen has done a really stellar job of documenting it, but it seems the whole approach is still very prone to mistakes and misunderstandings.

About the metrics, that's also something we've discussed, but nothing is implemented yet. I'd love to have some basic data on our plugin activities.
1 Like

The restructuring of the forums is step in the right direction, but I’d like plugin development being even more highlighted on this site.

Maybe adding a rating/comment system to the plugins as well? Keeping an updated list of plugins visible on the page, ranked by rating/downloads/activity?

1 Like

Yeah, setting up the plugin was fiddly and there were quite a few steps - but I just followed the two tutorial pages step by step and it all seemed to work.

1 Like
@zarch said:
Yeah, setting up the plugin was fiddly and there were quite a few steps - but I just followed the two tutorial pages step by step and it all seemed to work.


I have at least two plugins in the works so this is good to know. :) I'm much less afraid now.
1 Like
zarch said:
How many people have actually tried it so far? Is it going smoothly for everyone?


You mean developing a plugin or ImagePainter? For setting up the plugins I'm still trying to get mine to compile, think I'll have to ask normen to hold my hand tomorrow if I they don't compile :)
ImagePainter I sure will try, actually I'd like to make a plugin for drawing dynamic images in the SDK using it. But I'm stuck at getting access to the project classpath from the plugin. Does anyone know how?

The use case for me is that I have code that generates height maps and splat-maps for the terrain. That code uses some parameters as initial values (like noise level and so on). So I was thinking about a simple text area (script window) where I could write code to set the values and then call the generation of the heightmap and have it pre-viewed as an image. Right now I have a plugin that can execute javascript, the javascript returns a float[] and the plugin draws that as a grey-scale image.
But that could be generalized to visualize any image, like for quick hacking some image generation code. So I was thinking that the script window should expose an API rather than look for a float[], so that the script can use the API to draw stuffs on the screen and why not give the script an ImagePainter :)
1 Like
@jmaasing said:
ImagePainter I sure will try, actually I'd like to make a plugin for drawing dynamic images in the SDK using it. But I'm stuck at getting access to the project classpath from the plugin. Does anyone know how?

Add the jar as a "wrapped library", optionally expose its api publically to other plugins.
1 Like

Yeah, that shouldn’t be a problem. I mean the compiled code in my own project. Like I create a new SimpleGame and want my plugin to execute code in that SimpleGame project. Don’t know if that is possible, it’s going against the whole idea of plugin-isolation :slight_smile:

1 Like
@jmaasing said:
Yeah, that shouldn't be a problem. I mean the compiled code in my own project. Like I create a new SimpleGame and want my plugin to execute code in that SimpleGame project. Don't know if that is possible, it's going against the whole idea of plugin-isolation :)

I don't think thats a good way. The SDK will support attaching AppStates to an opened scene to execute and try out project code in addition to the Controls now. For accessing and instantiating classes in the project, thats easily possible using reflection and the classpath of the Project (also available through the ProjectAssetManager), as the "Add Custom Control" code does.
1 Like
@normen said:
I don't think thats a good way. The SDK will support attaching AppStates to an opened scene to execute and try out project code in addition to the Controls now. For accessing and instantiating classes in the project, thats easily possible using reflection and the classpath of the Project (also available through the ProjectAssetManager), as the "Add Custom Control" code does.

Thanks for the info. But as you say, attaching appstates to an opened scene is much better than my idea, that'll be great :)
1 Like
@jmaasing said:
You mean developing a plugin or ImagePainter? For setting up the plugins I'm still trying to get mine to compile, think I'll have to ask normen to hold my hand tomorrow if I they don't compile :)


Well at the time I meant ImagePainter but the question was ambiguous and I realised I was interested in both answers so I left it :D

@jmaasing said:

ImagePainter I sure will try, actually I'd like to make a plugin for drawing dynamic images in the SDK using it. But I'm stuck at getting access to the project classpath from the plugin. Does anyone know how?

The use case for me is that I have code that generates height maps and splat-maps for the terrain. That code uses some parameters as initial values (like noise level and so on). So I was thinking about a simple text area (script window) where I could write code to set the values and then call the generation of the heightmap and have it pre-viewed as an image. Right now I have a plugin that can execute javascript, the javascript returns a float[] and the plugin draws that as a grey-scale image.
But that could be generalized to visualize any image, like for quick hacking some image generation code. So I was thinking that the script window should expose an API rather than look for a float[], so that the script can use the API to draw stuffs on the screen and why not give the script an ImagePainter :)


That sounds similar in some ways to how we generate the Cards in HeroDex. The base Card just renders the background and the name at the top, then it passes the ImagePainter on to specific implementations for the various card types that each know how to render those card types.

How are you drawing the grey-scale Image atm? If it's within a jME3 window then you will be fine, otherwise you might need to either do something custom to render a jME3 Image or alternatively a new implementation of ImageRaster which wraps whatever you are using to display.

Sounds like an interesting project anyway :)
1 Like
@zarch said:
How are you drawing the grey-scale Image atm? If it's within a jME3 window then you will be fine, otherwise you might need to either do something custom to render a jME3 Image or alternatively a new implementation of ImageRaster which wraps whatever you are using to display.

Sounds like an interesting project anyway :)

It's just a simple hack at the moment, here's the code, don't know if I'll ever take it further. I draw using Java2D (Swing) but I was thinking that it should be possible to either make a new implementation of ImageRaster wrapping Java2D, or extract the data from a real ImageRaster, or even fake an ImagePainter :) Haven't looked into it.
1 Like

A wrapper for Java2D sounds like the best approach. I considered writing one myself but don’t have a real use for it right now. I’d be happy to add one into the ImagePainter library if someone did one though :smiley:

1 Like

You can actually make the ImagePainter calls go directly to AWT’s Graphics2D which could be hardware accelerated.

1 Like

That’s nice in theory but in practice it would struggle. For example you could accelerate drawing one BufferedImage into another BufferedImage but not drawing one Image into a BufferedImage (or vica versa). I suppose you could look at whether both ImageRaster contain a BufferedImage and then delegate to G2D but that would add a lot of bloat to ImagePainter…so really I guess you would want it to be in a new sub-class of IP that offers the BufferedImage functionality.



An ImageRaster implementation for G2D would be slower but allows the BufferedImage to be used in what is a small list of places now but I would expect that list to grow.

1 Like

Hmm, I was going to play with this… but my mac throws this at me. Do I really need java 7 to use this? =S

[java]

@Override

public void simpleInitApp() {

Box b = new Box(Vector3f.ZERO, 1, 1, 1);

Geometry geom = new Geometry("Box", b);



ImagePainter ip = new ImagePainter(Image.Format.RGBA8, 256, 256);

ip.paintRect(10, 10, 50, 50, ColorRGBA.Blue, ImagePainter.BlendMode.SET);



Texture2D texture = new Texture2D(ip.getImage());

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat.setColor("Color", ColorRGBA.Blue);

mat.setTexture("ColorMap", texture);

geom.setMaterial(mat);





rootNode.attachChild(geom);

}

[/java]

Code:
ALLVARLIG: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main] java.lang.UnsupportedClassVersionError: com/zero_separation/plugins/imagepainter/ImagePainter : Unsupported major.minor version 51.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) at java.lang.ClassLoader.defineClass(ClassLoader.java:615) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at mygame.Main.simpleInitApp(Main.java:30) at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225) at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130) at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207) at java.lang.Thread.run(Thread.java:680)
1 Like

Boo. Plz set the source level to 1.5 @zarch, normally jME3 is Java5 baseline.

1 Like