Text inside Windows that use showWithEffect

Hi,

Another text related issue has cropped up. This time when it is in a window that is made visible by showWithEffect(). On the first showing of the window, the text doesn’t show. If you subsequently hide the window, and then show it again, it will appear.

I -think- this started happening around the time you fixed opacity of text when used with effects. I am guessing its related.

This test case shows it happening :-

[java]

import com.jme3.app.SimpleApplication;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.math.Vector2f;
import com.jme3.renderer.RenderManager;
import tonegod.gui.controls.buttons.ButtonAdapter;
import tonegod.gui.controls.text.Label;
import tonegod.gui.controls.windows.Window;
import tonegod.gui.core.Screen;

/**

  • Demonstrates text inside containers that use fade effect to show doesn’t usually

  • show. This affects all sorts of windows, include things such as menus and combo boxes.
    */
    public class TestTextAndEffects extends SimpleApplication {
    public static void main(String[] args) {
    TestTextAndEffects app = new TestTextAndEffects();
    app.start();
    }

    @Override
    public void simpleInitApp() {
    flyCam.setDragToRotate(true);

     Screen screen = new Screen(this, "tonegod/gui/style/def/style_map.gui.xml");
     
     // Window 1 (show with effect)
     final Window window1 = new Window(screen, new Vector2f(200, 300));
     
     Label label1 = new Label(screen, new Vector2f(25, 70), new Vector2f(300, 24));
     label1.setText("This text usually won't show");
     window1.addChild(label1);
     
     screen.addElement(window1);
     window1.showWithEffect();
             
     // A button to allow window to be shown/hidden, showing that eventually text
     // will show if you click a few times
     ButtonAdapter button1 = new ButtonAdapter(screen, new Vector2f((screen.getWidth() / 2) - 100, screen.getHeight() - 50), new Vector2f(200, 32)) {
         @Override
         public void onButtonMouseLeftDown(MouseButtonEvent evt, boolean toggled) {
             if(window1.getIsVisible()) {
                 window1.hideWithEffect();
             }
             else {
                 window1.showWithEffect();
             }
         }
     };
     button1.setText("Toggle problem window");
     screen.addElement(button1);
     
     //
     guiNode.addControl(screen);
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    }

    @Override
    public void simpleRender(RenderManager rm) {
    }
    }

[/java]

EDIT 1: Think I’ve found the problem, or at least part of it. I noticed that the value for Effect.pass would go straight from 0.0 to 1.0 with no values at all. This meant that Effect.updateFadeIn() would not set any alpha at all. My fix is in Effect.updateFadeIn(). …

[java]
private void updateFadeIn() {
if (!init) {
initFades();
element.show();
init = true;
}
if (pass >= 1.0) {
disableShaderEffect();
isActive = false;
// don’t set > 1.0f
pass = 1f;
}

            // always update even if 1.0 is the first alpha value we set

// else {
element.getElementMaterial().setFloat(“EffectStep”, pass);
if (element.getTextElement() != null) {
element.getTextElement().setAlpha(pass);
}
if (element instanceof TextElement)
((TextElement)element).setAlpha(pass);
// }
}
[/java]

This doesn’t really explain why the pass variables jumps straight from 0 to 1, but at least the text is now visible.

EDIT 2: So it seems the the jump from 0 to 1 only happens with relatively small effect times. I think the combination of the default fade in time being 0.25 seconds, and the fact Java is still warming up, means the first frame takes more than 0.25 seconds, and so there is no time for a fade to happen.

RR

Sorry about the delay… been a real hell week for me.

I have a list of things to get to that is piling up, but have been working on a personal project… well… really for two reasons:

  1. To make the time I put in here worth while :wink:
  2. It help in the never-ending bug squashing quest.

I tend to find things fast when putting the library to practical use.

Question about this one. What duration are you setting on the Effect?

Also, even if it jumps directly to one, the final value passed to the shader should be one. So, if this isn’t happening, I know just where to go to fix this. Which is good :wink:

I’ll add it to the list of “Next Series of Updates” to make sure it is taken care of.

@t0neg0d said: Sorry about the delay... been a real hell week for me.

I have a list of things to get to that is piling up, but have been working on a personal project… well… really for two reasons:

  1. To make the time I put in here worth while :wink:
  2. It help in the never-ending bug squashing quest.

I tend to find things fast when putting the library to practical use.

Question about this one. What duration are you setting on the Effect?

Also, even if it jumps directly to one, the final value passed to the shader should be one. So, if this isn’t happening, I know just where to go to fix this. Which is good :wink:

I’ll add it to the list of “Next Series of Updates” to make sure it is taken care of.

As ever, no apologies needed :slight_smile: Yeh … the best way to find bugs is to actually use code in anger!

Regarding the duration, the problem happens with the 0.25 seconds that is used for all of the effects in the default styles. Changing this to say 2 seconds, and the problem is far less likely to happen, but … it still can. Particularly if this is the first time loading a game, when it is a little slower.

Oh! While on the subject of showWithEffect(), there is another little issue with this. I have a number AppStates that control one Window (this is a nice neat pattern so I use it often). So …

  1. In initialize(), a Window is shown with showWithEffect(). This window has a UID of “MyWindow”.
  2. In cleanup(), the Window is hidden with hideWithEffect().
  3. This appstate is toggled by a key combination handled by another appstate.

The problem happens if the player toggles this appstate on and off very quickly. Because hideWithEffect() doesn’t actually remove the window until the effect has finished, when the next showWithEffect() starts, you get a Conflicting ID exception. There are a few solutions to this :-

  • You can of course use a randomly generated UID for a such situations, but UIDs can be useful sometimes.

  • Before showWithEffect(), you can manually look for an elemenent with that UID and remove it before showing. Easy to do, but ideally you shouldn’t have to.

  • The solution I went with meant changing Element.hideWithEffect(). When this is used, BEFORE the effect starts, the element is removed from it’s parents list of Elements (and Screen’s), BUT, it is not removed from the scene allowing the effect to remain visible until it completes.

[java]
/**
* Hides the element using the current defined Hide effect. If no Hide effect is defined, the Element will hide as usual.
*/
public void hideWithEffect() {
Effect effect = getEffect(Effect.EffectEvent.Hide);
if (effect != null) {
if(effect.getIsDestroyOnHide()) {
// Actually remove from the parents child list, but don’t remove from the scene yet. This lets
// the effect complete, but if another component with same UID gets added again before the effect
// ends, it won’t cause problems
if(getElementParent() != null) {
getChildren().remove(this);
}
if(screen instanceof Screen) {
((Screen)screen).getElementsAsMap().remove(this.getUID());
}
}
if (effect.getEffectType() == Effect.EffectType.FadeOut) {
Effect clone = effect.clone();
clone.setAudioFile(null);
this.propagateEffect(clone, true);
} else
screen.getEffectManager().applyEffect(effect);
if (isVisibleAsModal) {
isVisibleAsModal = false;
screen.hideModalBackground();
}
} else
this.hide();
}
[/java]

The strange thing about this is, I don’t see this problem when using TextElement in place of BitmapText. I’m still not advocating using TextElement as I am still working on it… however setting alpha on TextElement never fails.

EDIT: Which can be done through the EffectManager currently.

As for the second issue… There are a number of ways to avoid this:

  1. Check the state of the Effect associated with EffectEvent.Show of the Element to ensure that it is either not currently active, or has completed before firing off the Hide effect.
  2. Use a GameTimer to fire off the event.
  3. Use an ExecuteAction to fire off the event (This is only a viable solution if you are using the 2D framework AnimElement class)
  4. Check for the existance of the UID to determine the state. This way you can delay the hide/show based on the existance of the Element.

I’ll likely port ExecuteAction to an Effect to allow for delayed execution of methods, this way… you can check the current state of the Show effect and call hideWithEffect as soon as the Effect has completed it’s operation. This can be triggered from cleanup() of an AppState, letting you unload the AppState and still manager the UI components of that AppState after the fact.

“The strange thing about this is, I don’t see this problem when using TextElement in place of BitmapText. I’m still not advocating using TextElement as I am still working on it…. however setting alpha on TextElement never fails.”

Oh ok. I could try that here I guess, see if I see the same thing. Am REALLY looking forward to a completed TextElement. This blurry text problem, which is my own particular text related bugbear, is the last thing making my UI look a bit unpolished (apart from my own lack of artistic talent). I will rejoice when that little annoyance is gone. So TextElement is going to solve all our problems and bring about world peace and stuff like that. No pressure :expressionless:

re. the 2nd issue. Ok, thanks, I’ll investigate some of those work arounds. I’ll be honest though, I am currently quite happy with my own solution to this, as it means I don’t need any extra code to check effect status or some kind of timer, I just use the normal show/hide methods as you’d expect them to be used. I cant see any obvious problems this approach might cause, so unless you can, I will probably stick with it.

You’ve actually answered another question I had about effects, was wondering if it was possible to invoke code when effects complete. That would be useful!

One last thing … honest :wink:

Is this normal :-

[java]
screen.addElement(optionsWindow);
optionsWindow.hide();
optionsWindow.showWithEffect();
[/java]

It seems you have to hide a window before showing it when using effects. Without this hide first, I see the window appear very briefly before fading in.

RR

@rockfire said: "The strange thing about this is, I don’t see this problem when using TextElement in place of BitmapText. I’m still not advocating using TextElement as I am still working on it…. however setting alpha on TextElement never fails."

Oh ok. I could try that here I guess, see if I see the same thing. Am REALLY looking forward to a completed TextElement. This blurry text problem, which is my own particular text related bugbear, is the last thing making my UI look a bit unpolished (apart from my own lack of artistic talent). I will rejoice when that little annoyance is gone. So TextElement is going to solve all our problems and bring about world peace and stuff like that. No pressure :expressionless:

re. the 2nd issue. Ok, thanks, I’ll investigate some of those work arounds. I’ll be honest though, I am currently quite happy with my own solution to this, as it means I don’t need any extra code to check effect status or some kind of timer, I just use the normal show/hide methods as you’d expect them to be used. I cant see any obvious problems this approach might cause, so unless you can, I will probably stick with it.

You’ve actually answered another question I had about effects, was wondering if it was possible to invoke code when effects complete. That would be useful!

One last thing … honest :wink:

Is this normal :-

[java]
screen.addElement(optionsWindow);
optionsWindow.hide();
optionsWindow.showWithEffect();
[/java]

It seems you have to hide a window before showing it when using effects. Without this hide first, I see the window appear very briefly before fading in.

RR

Suggestions for the blurry issue. Create the font with a 512x512 png image with a much larger base size (keep the default render size the same) and then adjust the textures min/mag filter options. This should allow you to find a happy medium between pixelated and smooth without being too much of either. Between this and the fix you came up with (non-float render size… though, this doesn’t work for Android) should be all that is needed to solve that problem.

What font creator are you using?

And yes on the hide after adding… it happens in the same frame, so I haven’t noticed an issue with it. are you seeing something? Or just wondering due to the odd way of handling them?

I guess I could provide alternate addElement and addChild methods that allow you to set the visibility there?

@t0neg0d said: Suggestions for the blurry issue. Create the font with a 512x512 png image with a much larger base size (keep the default render size the same) and then adjust the textures min/mag filter options. This should allow you to find a happy medium between pixelated and smooth without being too much of either. Between this and the fix you came up with (non-float render size... though, this doesn't work for Android) should be all that is needed to solve that problem.

What font creator are you using?

Well … I didn’t actually create them. I was actually supplied with some Ogre .fontdef files, and I wrote a converter to create .fnt files from the these (now I know more about JME, I would do this differently, and probably write a proper asset loader for these). However, thanks … you have given me something to go on, I will try your suggestions :slight_smile:

Regarding the hide thing … no, I am not seeing any issues doing that, it just didn’t seem natural. Is there any reason you can’t just hide() inside showWithEffect() if the element is visible?

@rockfire said: Well .. I didn't actually create them. I was actually supplied with some Ogre .fontdef files, and I wrote a converter to create .fnt files from the these (now I know more about JME, I would do this differently, and probably write a proper asset loader for these). However, thanks .. you have given me something to go on, I will try your suggestions :)

Regarding the hide thing … no, I am not seeing any issues doing that, it just didn’t seem natural. Is there any reason you can’t just hide() inside showWithEffect() if the element is visible?

If you grab the latest commits, the following issues should be fixed:

  • Text fade in and fade out should end at an alpha of 1 on fade in and an alpha of 0 on fade out now, despite the time associated with the effect or any lag that might occur during the transition.
  • Added overloaded methods for Screen.addElement and Element.addChild that allow you to pass in a boolean to auto-hide elements… so, you would call: screen.addElement(element, true); to auto hide, etc, etc.
@t0neg0d said: If you grab the latest commits, the following issues should be fixed:
  • Text fade in and fade out should end at an alpha of 1 on fade in and an alpha of 0 on fade out now, despite the time associated with the effect or any lag that might occur during the transition.
  • Added overloaded methods for Screen.addElement and Element.addChild that allow you to pass in a boolean to auto-hide elements… so, you would call: screen.addElement(element, true); to auto hide, etc, etc.

Excellent :slight_smile: Both of these work good. As ever, thanks for the time.

RR