Exciting news! And… um… new Documentation… dun dun duuuun

Hey all!

I’m super excited to report that I am squaring away the library for a solid Beta release (or Beta 2… or whatever). Anyways, point being, there a lot of fixes and updates which I am really excited about. But before going into those, I wanted to announce the new Documentation.

Documentation?? What’s all this about??! Well, I decided in place of documentation which is long, boring and hard to keep up on, I am squaring away a new Test Bed App, that covers absolutely EVERYTHING you could want to know about how to use the library, including:

  • In app screen resolution changing
  • a LayoutHelper class that does more than just layouts, it also does smart repositioning when you change resolutions.
  • A scaling manager for relative resizing of components and fonts
  • I even threw in an extra that shows you how to rebuild the FilterPostProcessor filter chain when you change resolutions.
  • How to use embedded SubScreens (projected 2D on 3D)
  • How to make use of the 3D spatial event handling support.
  • How to Create custom Elements, like–
    ---- Animated buttons
    ---- Collapse-able panels within a ScrollPanel
  • How to use exactly every single component that comes with the library!
  • How to build a Drag & Drop inventory system
  • How to build a click-to-pick-up, click-to-place inventory system.
  • How to etc, etc, etc

I’ll be using this as my personal test bed app from now on and will update it with new content as I go so you can just grab the latest version and your hands-on documentation is ready to go.

In place of text-based documentation for the library, I’ll likely do a write up on how to extend the AppStateCommon class to add your own test to the list of managed tests within the app.

Anyways, here is a quick vid of of the app and then I’ll go through a list of the updates/bug fixes I’ve been working on for the new release.

(video won’t finish processing for like an hour or so… check back if you must see)
[video]http://youtu.be/9KzgEqA5q4o[/video]

So… now… about the updates:

  • First and foremost, the intermittent picking bug is finally resolved. Couldn’t be more thrilled about this one.
  • ColorWheel got a facelift and now works with atlasing and on Android
  • SpriteElement got an overhaul that changed the internal frame handling. You can now also set the a custom frame order and integrate an alpha map into the sprite sheet.
  • Fixed a minor bug in the visuals of the Dial control
  • Added content paging to the ScrollPanel control… if enabled, only what is visible within the clipping area is actually in the rendered scene. This will increase performance dramatically for large content based scroll areas.
  • Made some improvements to the original ScrollPanel / Menu / drop-down lists to account for content margins and padding
  • Fixed many smaller issues with various things in both the base Element class and Screen.
  • Fixed a minor issue in the default atlas image
  • Fixed an issue with the scroll bar gap property
  • Added focus/target/event element clearing for certain common events.
  • And a bunch more I just can’t remember at the moment.

I have a couple more announcements that a relevant to this subject (in a round about way):

  1. I’ll be putting together a similar app that focusing completely on the the how/what/where/why/whens of the 2D Framework after this is finalized.
  2. And this one is important to those using the library for Android dev. On Tues. my new Note 3 and Tab 2 will be here and I will be able to finally resolve the 2D framework issues for that series of devices (being the few Samsung devices that just hate me)
10 Likes

Heh… forgot to mention there is a new LabelElement class (replacement for Label) that uses TextElement as it’s backing in place of BitmapText. Seeeeew… no more alignment fighting for labels. F’ing HATED the Label class.

I’ll likely add this as the default Label for Buttons soon as well, still letting you use the old BitmapText if you want… but honestly… I can’t think of a reason why you would >.<

EDIT: Not to mention, you can animate the text if you opt for the new Label.

2 Likes

Gonna be adding vids of the more interesting tests as I get this together…

Here is the test for the 2D Emitter: (Also show how to use the Joystick for Android dev)
[video]http://youtu.be/lGmf0jPJtT0[/video]

And the test for Animated Text:
[video]http://youtu.be/IKZZZNlZbkM[/video]

There is also a LabeledButton class that shows how to use animate text with Button effects

1 Like

Another quick note…

The static LayoutHelper class has been moved into the library. It is by no means the only thing that will be added to support layouts, but it is a really useful utility class, saves you from creating a million Vector2f’s when defining your ui and has the smart repositioning method that just simply kicks ass =)

I’ll likely genericize the ScaleManager as well and add that as another utility class. The relative scaling of components and fonts is beyond priceless for Android dev.

The test for adding/removing SubScreens (Projected UI’s) into your 3D scene.

[video]http://youtu.be/ewieeimn48Y[/video]

3 Likes

Few more updates that are going to be available after tonight:

  1. Now that the picking issue is resolved, I’ve added a method to Element to update the zOrder local to the parent Element. Just call el.bringToFront() for objects that are children of another element. This method has no effect on screen level Elements, as this is an automatic function.
  2. This is specifically for @sgold and focus element refresh request - I’ll be adding the focus clearing tonight, as I’m feeling fairly confident about it… however, to start, the method will need to be called manually until I can finish up the tests and detemine exactly where/when this should be called automatically. To reset this, just call screen.forceFocusElementRefresh();

That’s it for now.

First of all, i want to say that i realy like what you doing there and i can tell the same for almost all stuff i’ve seen you did, realy. I miss word there… but that’s realy cool.
JME team isn’t forgotten :smiley:

Then, this will sound realy dumb but… where is the Documentation ? did i miss something in the thread since, i’ve downloaded the latest build and latest source code following this statement :

@t0neg0d said: I’ll be using this as my personal test bed app from now on and will update it with new content as I go so you can just grab the latest version and your hands-on documentation is ready to go. ... ... That's it for now.
And, i didn't found the launcher. I feel like i've missed something somewhere. To be clear about my issue and what i'm looking for, I'm looking for the layout you're using to make the showcase, the one in the video, . Could i have some hint plz.

Thx.

@kobRoah said: First of all, i want to say that i realy like what you doing there and i can tell the same for almost all stuff i've seen you did, realy. I miss word there... but that's realy cool. JME team isn't forgotten :D

Then, this will sound realy dumb but… where is the Documentation ? did i miss something in the thread since, i’ve downloaded the latest build and latest source code following this statement :

And, i didn’t found the launcher. I feel like i’ve missed something somewhere. To be clear about my issue and what i’m looking for, I’m looking for the layout you’re using to make the showcase, the one in the video, .
Could i have some hint plz.

Thx.

Hey you… the test app is being built right now. Sorry if that wasn’t clear in the post. I’m still building out each of the tests to make sure that they cover as much about the library as possibly. It won’t take me that long to finish, however, I want to be thorough =)

As soon as it is complete, I’ll update the display page for the plugin with the link to the download and make sure it is posted both here and on the outdated Wiki (which will get at least a minimal overhaul).

EDIT: In the meantime, feel free to ask as many questions as you need… either in the forum or in a PM.

This test is probably cooler than most because it shows a few things:

  1. 3D Spatial event support via the library
  2. How to leverage classes like GameTimer and TemporalAction to run effects against Models/Geometries
  3. How to utilize the Screen’s ToolTips & custom Cursors with the Spatials
  4. How to build a simple Drag & Drop or Point & Click inventory system

[video]http://youtu.be/BJFbm30KnME[/video]

2 Likes

Taking a moment to ramble about porting the ScaleManager class over to the library…

I picture it working this way:

Instead of how I have it set up now, which is it determines the scaling factor and the you cal getGameScale… or getFontScale, I’m going to change this to allow you to set the base reference width/height… say… 400x720 (portrait mode on Android devices as a for instance) and the class will refactor the scaling ratio. After this, you would simply call scale(Element el) and your control will be returned scaled (and positioned) for the screen resolution/dpi.

Sooo… you choose a resolution to develop your game in and the ScaleManager will ensure that it looks and positions your gui exactly the same on any device/screen resolution/dpi your app is run on.

Brain dump complete… sorry

2 Likes

hi @T0neg0d,

@t0neg0d said: 1. 3D Spatial event support via the library 2. How to leverage classes like GameTimer and TemporalAction to run effects against Models/Geometries 3. How to utilize the Screen’s ToolTips & custom Cursors with the Spatials 4. How to build a simple Drag & Drop or Point & Click inventory system

Does this one is a control ? i mean can we create it like a control and use it like Geometry.addControl(element) or Node.addControl(element).
you explain there 3D GUI how to configure something like it, but it work with an ExtendedNode, and this node need to be parent of the geometry to be activated, is the method show here use the same working style ?

@kobRoah said: hi @T0neg0d,

Does this one is a control ? i mean can we create it like a control and use it like Geometry.addControl(element) or Node.addControl(element).
you explain there 3D GUI how to configure something like it, but it work with an ExtendedNode, and this node need to be parent of the geometry to be activated, is the method show here use the same working style ?

The extended node can encapsulate anything… another node… a bunch of other nodes… a geometry… multiple geometries. And it really is just a node… no control to add. The screen class sees the node as whatever listeners have been implemented and forwards the appropriate events to the listeners event handlers. From there, you can do anything you like with the events.

In the test above, I am running effects against the JME primitive geometries to scale them using bounceOut Interpolation to make them look Jello-ish. As well as changing the color, setting tool tip text and applying a custom cursor on focus/lose focus events. I used the MouseButtonListener to call a method for removing the clicked spatial and creating a DragElement to represent it (storing the original spatial as user data of the node.

Here is the InteractiveNode class I put together with a few getter/setters to store node specific data and the listener event handlers: Note: you could just store this get/setUserData so you can save to j3o

[java]
/**
*

  • @author t0neg0d
    */
    public abstract class InteractiveNode extends Node implements MouseFocusListener, MouseButtonListener {
    private ElementManager screen;
    private GameTimer timer;
    private Effect fx;
    private boolean xDir = true;
    private boolean yDir = false;
    private float xAmount = 0.5f;
    private float yAmount = 0.5f;
    private Material defMat, hlMat;
    private String toolTipText;
    private String icon;
    private boolean isInScene = true;

    public InteractiveNode(ElementManager screen) {
    this.screen = screen;

     initTimer();
    

    }

    private void initTimer() {
    timer = new GameTimer(0.5f) {
    @Override
    public void onComplete(float time) {
    xDir = !xDir;
    yDir = !yDir;
    }
    @Override
    public void timerUpdateHook(float tpf) {
    scaleSpatial(this.getPercentComplete());
    }
    };
    timer.setAutoRestart(true);
    timer.setInterpolation(Interpolation.bounceOut);
    }

    public void scaleSpatial(float percent) {
    float percentX = (xDir) ? percent : 1f-percent;
    float percentY = (yDir) ? percent : 1f-percent;
    if (timer.getRunCount() == 0)
    setLocalScale(1+(xAmountpercentX),1,1);
    else
    setLocalScale(1+(xAmount
    percentX),1+(yAmount*percentY),1);
    }

    public void setDefaultMaterial(Material mat) {
    this.defMat = mat;
    setMaterial(defMat);
    }

    public void setHighlightMaterial(Material mat) {
    this.hlMat = mat;
    }

    public void setToolTipText(String text) {
    this.toolTipText = text;
    }

    public String getToolTipText() { return this.toolTipText; }

    public void setIcon(String icon) {
    this.icon = icon;
    }

    public String getIcon() { return this.icon; }

    public void setIsInScene(boolean isInScene) {
    this.isInScene = isInScene;
    }

    public boolean getIsInScene() { return isInScene; }

    public void onGetFocus(MouseMotionEvent evt) {
    if (!screen.getAnimManager().hasGameTimer(timer)) {
    timer.resetRunCount();
    timer.reset(false);
    timer.setAutoRestart(true);
    xDir = true;
    yDir = false;
    screen.getAnimManager().addGameTimer(timer);
    }
    setMaterial(hlMat);
    ((Screen)screen).setForcedCursor(StyleManager.CursorType.HAND);
    if (screen.getUseToolTips() && toolTipText != null)
    ((Screen)screen).setForcedToolTip(toolTipText);
    }
    public void onLoseFocus(MouseMotionEvent evt) {
    timer.setAutoRestart(false);
    timer.endGameTimer();
    setLocalScale(1);
    setMaterial(defMat);
    ((Screen)screen).releaseForcedCursor();
    ((Screen)screen).releaseForcedToolTip();

    }
    public void onMouseLeftPressed(MouseButtonEvent evt) {
    onSpatialMouseDown(evt);
    }
    public void onMouseLeftReleased(MouseButtonEvent evt) {
    onSpatialMouseUp(evt);
    }
    public void onMouseRightPressed(MouseButtonEvent evt) { }
    public void onMouseRightReleased(MouseButtonEvent evt) { }

    public abstract void onSpatialMouseDown(MouseButtonEvent evt);
    public abstract void onSpatialMouseUp(MouseButtonEvent evt);
    }

[/java]

Note: you DO have to enable this via the screen:

[java]
screen.setUse3DSceneSupport(true);
[/java]

The node can be child of another node and work ?
I mean, i got a Node(with geometry and stuff), his parent must not change, so if i use this GUInode, have i to make my node child of it to work with ?

@kobRoah said: The node can be child of another node and work ? I mean, i got a Node(with geometry and stuff), his parent must not change, so if i use this GUInode, have i to make my node child of it to work with ?

It can be nested in any way you need it to be… or you can simply wrap another node and forget it is even there. The extended node just has event handlers associated with it… it also has the added benefit of effecting global transforms of anything it contains.

So it should work fine in whatever the situation may be.

EDIT: Little bit further explanation… as long as the geometry being picked can find one of these listener nodes somewhere between it and the root node (parent encapsulation), it works just fine.

RootNode > MyCollidablesNode > TreesNode > MyInteractiveNode > TheLoadedModelNode > 3 Geometries

Each of the three contained geometries would trigger the event node 2 levels up.

I guess I should also note that you can have more than one extended node as a parent, but they would have to implement different listeners. Why would you want to do this? Well… a simple for instance would be:

RootNode
— MyHighlightableObjects (a node that implements MouseFocusListener and starts a cool particle emitter around the picked object when you mouse over it)
— --- MyClickableBoxes
— --- MyClickableSpheres

Everything contained within MyHighlightableObjects would inherit the effect above… And all of the different clickable child nodes implementing MouseButtonListener would perform different tasks based on which node the geometry was under.

EDIT: To find out what the last collision was from a larger encapsulation node, you can call: screen.getLastCollision(); from within the event handler

This getting fancy than ever :)) Awesome… I think this is the point i also need a switch from Nifty GUI to Tonegod GUI for one big evolution finally!!

I remember watched some topics about Layouting elements in the GUI a while ago and also read your code in Emitter editor. I want to say a humble opinion that’s it not what I really want to do layouting. Even in Java code, because it’s quite (tooo) verbose…

What i do (i did the same with NiftyGUI) is to create an abstract LayoutManager with some concepts: LayoutManager, LayoutBuilder, LayoutEvent… which later has Screen and Element as the two strict components. Ordering, TreeTraveser, EventBus of Guava help me the refesh and arranges the elements in atribinary bottom-up, top-down or ad-hoc orders, independent with the order of adding or the containment of elements.

[java]
ButtonAdapter newButton = new ButtonAdapter(this, “btnInGame”, new Vector2f()) {
@Override
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
mainMenuState.toState(InGameState.class);
}
};
newButton.setText(“SingleGame”);
this.addElement(newButton);

    //Now resolve the layout
    Layout layout = new Layout(this);
    layout.$(newButton).pos(100,100).size(100,100).set();
    layout.active(this);

[/java]

Thanks to the absolute nature of tonegod gui elements, my LayoutManager can work exactly beside of the the background layouting of the library and not a big performance cost.

The cool things (which i also successfully done with Nifty) are:

  • the event dispatching method which are long time headache of swing now can be take care of by eventbus.
  • elements can be update (refresh) partly, it’s text (or other data) and its reprentation (layout, style) are lousely again.
  • functions over layouts and presentation (skew, animations, effects, …) and also over data (binding, mapping …) are open.
  • query … :slight_smile:

As I going to quit my company to go indie, I also consider working in an Editor for the Tonegod GUI beside of my NiftyGUI… :slight_smile: At least now I have tons of free time for the next months.

1 Like

What i’m thinking about is not nested like this it’s more :

  • rootNode > MyNode > Collidable(Geometry)
    |-> GUINode

The GUInode isn’t the child of “Collidable(Geometry)” but child off “rootNode > MyNode”

On the provided exemple before, when i tryed what you wrote it works, no point about it, but when i try it how i need it to work, it doesn’t.
Well it make me end with using a control XD Pretty simple in fact :
[java]package mygame.tonecontrol;

import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;

/**
*

  • @author roah
    */
    public class ToneControl extends AbstractControl {
    private InteractiveNode toneNode;

    public ToneControl(InteractiveNode toneNode) {
    this.toneNode = toneNode;
    }

    @Override
    public void setSpatial(Spatial spatial) {
    spatial.getParent().attachChild(interactiveNode);
    interactiveNode.attachChild(spatial);
    super.setSpatial(spatial);
    interactiveNode.setDefaultMaterial(((Geometry) ((Node) spatial).getChild(0)).getMaterial());
    }

    public void remove(){
    Node s = interactiveNode.getParent();
    s.detachChild(interactiveNode);
    s.attachChild(spatial);
    }

    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) { }
    }[/java]
    Let me know what you thing about the control, there is some issue on this since but hey :D, here is the idea…
    Ps: i forgot to mention the control only work if attach to something with a parent, well on some way there is no need of the control otherwise, even if i feel like it will be more easy to use, having a Control more than a Node.

1 Like

I want just to say that this library became really powerful and well integrated ! :slight_smile: congratulation ! :smiley:

1 Like
@atomix said: This getting fancy than ever :)) Awesome... I think this is the point i also need a switch from Nifty GUI to Tonegod GUI for one big evolution finally!!

I remember watched some topics about Layouting elements in the GUI a while ago and also read your code in Emitter editor. I want to say a humble opinion that’s it not what I really want to do layouting. Even in Java code, because it’s quite (tooo) verbose…

What i do (i did the same with NiftyGUI) is to create an abstract LayoutManager with some concepts: LayoutManager, LayoutBuilder, LayoutEvent… which later has Screen and Element as the two strict components. Ordering, TreeTraveser, EventBus of Guava help me the refesh and arranges the elements in atribinary bottom-up, top-down or ad-hoc orders, independent with the order of adding or the containment of elements.

[java]
ButtonAdapter newButton = new ButtonAdapter(this, “btnInGame”, new Vector2f()) {
@Override
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
mainMenuState.toState(InGameState.class);
}
};
newButton.setText(“SingleGame”);
this.addElement(newButton);

    //Now resolve the layout
    Layout layout = new Layout(this);
    layout.$(newButton).pos(100,100).size(100,100).set();
    layout.active(this);

[/java]

Thanks to the absolute nature of tonegod gui elements, my LayoutManager can work exactly beside of the the background layouting of the library and not a big performance cost.

The cool things (which i also successfully done with Nifty) are:

  • the event dispatching method which are long time headache of swing now can be take care of by eventbus.
  • elements can be update (refresh) partly, it’s text (or other data) and its reprentation (layout, style) are lousely again.
  • functions over layouts and presentation (skew, animations, effects, …) and also over data (binding, mapping …) are open.
  • query … :slight_smile:

As I going to quit my company to go indie, I also consider working in an Editor for the Tonegod GUI beside of my NiftyGUI… :slight_smile: At least now I have tons of free time for the next months.

I completely agree that the lack of Layouts is the the big missing piece… I just can’t make up my mind on the best approach.

Recently I added a static LayoutHelper class that lets you advance x & y independently by passing in the last element, adding padding and/or line feed… but the real intent of the class was to provide a way to do smart re-positioning when you change screen resolutions. Oh, and a few reusable Vector2fs, etc.

The class needs to leverage Docking behavior still, but it should provide a good backing for LayoutX type classes, once complete.

I think prior to actually starting Layouts, it’s important to get the ScaleManager in place as well. This will provide a simple way to ensure your components stay relative sized to the base resolution you define as your development resolution. EDIT: If you choose to enable the behavior.

Between these two classes, implementing Layout classes should become easy and I am hoping at that point I can take the best parts of the different approaches people have been nice enough to share and find a solution that will work for most cases.

EDIT: And provide a simple way (leveraging the LayoutHelper & ScaleManager) for users to add their own LayoutX type classes if the provided ones aren’t enough.