[Nifty1.3] Multiple Nifty screens (Solved)

Hi,



I can now compile my project :slight_smile:

But I have a little problem.

I’ve created a system that load multiple Nifty screens. All referenced inside a toolbar.



Here is a schema :





By clicking on one of the toolbar buttons, you decide if the corresponding screen is displayed or not.





The problem is :

If I decide screen 1 and screen 3 must be displayed, I can’t access to screen 3 buttons, even if it’s displayed above screen 1.



If I hide screen 1, I gain the contol of my ‘screen 3’ buttons back.



Could it be the opposite ? :slight_smile:

I think there can’t be multiple screens displayed at the same time.

Create multiple layers instead.

1 Like

It’s possible to have multiple screen ( Since I already did that with Nifty 1.2 ).

It works with Nifty 1.3 too.



I can’t describe all of them inside one XML. ( I have many of them. And depending on the place I am, some will be available and some not )



The problem is in catching the button clicks. :slight_smile:

uhm, how do you do the actual screen switching then? you can have mutliple screens of course but you can only display one at a given moment. at least I would not know how to display multiple screens at once with nifty xD



so how do you switch screens? is it a simple gotoScreen() call or do you use something special?

If you’re creating multiple “Nifty” objects, its likely that some of the input events get consumed along the way by some nifty before it gets to your nifty

@Momoko fan :

I think that’s exactly the problem. The first Nifty display to consume the event is the first one that has been added.

But the one that is displayed on the top of the screen is the last one added.



So what I was wondering is : Is it possible to change the order when checking event catching on Nifty displays. That way, the first Nifty display to be checked will be the one one the top of the screen ( → The last one added, and not the first one )



@void256 :

In fact, I’m managing Nifty display like layers. I use then as mother layers.

Here is a picture to display that :





And for displaying the each sheet or not, I use the gotoScreen() of each one



In fact, each of my Nifty sheets contains at least two screen.

  • screen = hide
  • screen = start



    Here is a simple one :

    [java]

    <?xml version=“1.0” encoding=“UTF-8”?>

    <nifty>

    <useStyles filename=“assets/Templates/Styles/ae-styles.xml”/>

    <useControls filename=“assets/Templates/Controls/ae-controls.xml” />



    <!-- notify Nifty that it now has a new effect called “textTyping” and that it lives in the given class -->

    <registerEffect name=“textTyping” class=“com.didigame.acariaempire.gui.effects.TextTyping”/>





    <screen id=“hide” controller=“com.didigame.acariaempire.dialog.DialogToolbarEltController” />

    <screen id=“start” controller=“com.didigame.acariaempire.dialog.DialogController” >

    <layer id=“mainLayer” width=“100%” height=“100%” childLayout=“horizontal”>



    <panel width=“5%” />

    <!-- Col 0 : text and answers -->

    <panel width=“70%” height=“100%” align=“center” valign=“center” childLayout=“overlay”>



    <image width=“100%” height=“100%” align=“center” valign=“center” filename=“dialogBg.png”

    imageMode=“resize:100,320,100,75,100,320,100,500,100,320,100,75” />



    <panel width=“100%” height=“100%” align=“center” valign=“center” childLayout=“vertical”>

    <panel width=“100%” height=“70%” align=“center” valign=“center” childLayout=“horizontal”>

    <panel width=“100px” />

    <panel width="" height=“100%” align=“center” valign=“center” childLayout=“vertical”>

    <!-- Line 0 : text -->

    <panel height=“50px” />

    <text id=“txtTitle” width=“100%” height=“30px” font=“titleDialog.fnt” text=“Interlocuteur” align=“center” valign=“top” textHAlign=“left” textVAlign=“top” color="#00ff" />

    <panel height=“5px” />

    <text id=“txtSentence” width=“100%” height="
    " font=“textDialog.fnt” text="" align=“center” valign=“top” textHAlign=“left” textVAlign=“top” color="#000f" />

    </panel>

    <panel width=“100px” />

    </panel>



    <panel width=“100%” height=“30%” align=“center” valign=“center” childLayout=“horizontal”>

    <panel width=“100px” />

    <panel width="" height=“100%” align=“center” valign=“center” childLayout=“vertical”>

    <!-- Line 1 : answers -->

    <panel id=“answerPanel” width=“100%” height="
    " childLayout=“vertical” />

    <panel height=“50px” />

    </panel>

    <panel width=“100px” />

    </panel>

    </panel>

    </panel>



    <panel width=“5%” />



    <!-- Col 1 : portrait -->

    <panel width=“20%” height=“100%” align=“center” valign=“center” childLayout=“center”>



    <control id=“portraitCtrl” type=“portrait” height=“200px” width=“200px” align=“center” valign=“center” />

    </panel>

    </layer>

    </screen>

    </nifty>

    [/java]



    Sheets available on a place are described in an other xml.

    Example :

    [java]

    <view background=“Menu.dds” >

    <sheets>

    <sheet file=“worldMap.xml” />

    <sheet file=“sheet_start.xml” />

    <sheet file=“characterJobs.xml” />

    </sheets>

    […]

    </view>

    [/java]

    So when I load a place ( View ), I load one Nifty display for each sheet available

    [java]

    public class SheetCreator implements Callable<Object> {



    private String xmlFile;

    private ScreenController controller;



    public SheetCreator( String xmlFile )

    {

    this.xmlFile = xmlFile;

    this.controller = null;

    }



    public SheetCreator( String xmlFile, ScreenController controller )

    {

    this.xmlFile = xmlFile;

    this.controller = controller;

    }





    @Override

    public Object call() throws Exception

    {

    //application.getToolbarController().registerSheetController( controller );

    NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay( ViewManager.getAssetManager(),

    ViewManager.getInputManager(),

    ViewManager.getAudioRenderer(),

    ViewManager.getGUIViewPort() );

    Nifty nifty = niftyDisplay.getNifty();

    if( controller == null )

    nifty.fromXml( xmlFile, AbstractToolbarEltController.HIDESCREEN );

    else

    nifty.fromXml( xmlFile, AbstractToolbarEltController.HIDESCREEN, controller );



    // attach the nifty display to the gui view port as a processor

    ViewManager.getGUIViewPort().addProcessor(niftyDisplay);



    return null;

    }



    }

    [/java]



    And the tips is in the controller of the screen hide. All those hide screen controller extends a class AbstractToolbarEltController

    And inside this one, during the bond, it register itself to the toolbar element.

    ( Which leads to the creation of a button inside it that enable to switch between screen “hide” and screen “start” of the sheet )

    [java]

    public class SheetRegistration implements Callable<Object> {



    private ToolbarController toolbar;

    private AbstractToolbarEltController controller;



    public SheetRegistration( ToolbarController toolbar, AbstractToolbarEltController controller )

    {

    this.toolbar = toolbar;

    this.controller = controller;

    }





    @Override

    public Object call() throws Exception

    {

    //We have to wait for the initialization of the sheet before adding element

    if( ! toolbar.isInit() )

    {

    Thread.sleep( 100 );

    SheetManager.addTask( new SheetRegistration( toolbar, controller ) );

    return null;

    }



    Vector<AbstractToolbarEltController> controllerList = toolbar.getControllerList();

    Vector<CustomImageButtonControl> toolbarElements = toolbar.getToolbarElements();



    if( controllerList.contains( controller ) )

    return null;



    int size = controllerList.size();

    if( size >= toolbar.getMaxToolbarElements() )

    {

    LogManager.warn( this, “The toolbar don’t have enough slot for storing all sheets. Sheet " + controller.retrieveSheetName() + " not available” );

    return null;

    }

    controllerList.add( controller );



    //

// Set effect
//
String style = controller.retrieveIconStyle();
toolbarElements.get( size ).setEffect( style , controller.isDisplayed() );

return null;
}

}
[/java]

Just make sure that the area where the buttons are is not “visibleToMouse” in any of the other screens

Yeah, I will need to check all my screens to be sure that images or simple panels are not visible to the mouse.

But I can’t do that for buttons.



Some time I will have a button on the same place for more than on screen.

( In the example above, it’s the case for the “save button” of the Menu and some “town button” of the map. )



The button I see on my screen is the “save button” so I think that the mouse click need to be consume on the “save button” click event.

Like inside on Nifty display, the layer on top is prior to consume the event.



I know that my use of Nifty displays is a little border line but… I still think that my request make sense :slight_smile:

From what I see, as long as the menu appears on top and gets all the mouse clicks, you really shouldn’t be having this problem.

The toolbar appears to the side and no other part of the gui goes there so it should receive all clicks

The problem is there :



The Menu do appear one the top, but the one receiving the click is the Map because it has been added before.

If I create a new screen shot whithe the Menu hidden, you will see that the map have buttons too.



And when I try click on the Save button, I’m teleported to the town corresponding to the map button behind the menu xD





I will give you an other example that may be better :





Here I added a new sheet : When this sheet is on, the storyteller explain to the player what it’s going one.

And I have done it so that the other GUI are not accessible.



But in fact, I can’t even click on the Skip button.

When I click on it, the event that is triggered is the one of the map that is below.

I can click on the toolbar too. ( And I don’t want that in this case )

Okay I see what you mean now. I guess this is more of a nifty issue then because really the element on top should be receiving the clicks.

Well, in fact : Inside a Nifty display, it’s the element one top that receive the clicks ( I havn’t checked it yet for Nifty1.3 )



The problem is when I have more that one Nifty display.

Each one of my sheet is added via :

[java]

ViewManager.getGUIViewPort().addProcessor(niftyDisplay);

[/java]



I don’t really know on which side the problem resides but I think it has something to do with the last upgrade : Nifty doesn’t consume input event.



Before that I did not have this problem. All Nifty display received the click and Sometimes I add 3 button clicked with only on click :slight_smile:



What I suppose is happening :



* When I’m adding the sheets :

guiViewPort : { NiftyDisplay0 };

guiViewPort : { NiftyDisplay0, NiftyDisplay1 };

guiViewPort : { NiftyDisplay0, NiftyDisplay1, NiftyDisplay2 };

[…]

simpleApplication




* When I do a mouse click :



Previous version :

click on point P(X,Y)

guiViewPort part :

is there a button on point P for NiftyDisplay0 ? Yes : doAction() / No : Continue.

is there a button on point P for NiftyDisplay1 ? Yes : doAction() / No : Continue.

is there a button on point P for NiftyDisplay2 ? Yes : doAction() / No : Continue.



simpleApplication part :

click received one point P




New version :

click on point P(X,Y)

guiViewPort part :

is there a button on point P for NiftyDisplay0 ? Yes : doAction() + EndTreatment() / No : Continue.

is there a button on point P for NiftyDisplay1 ? Yes : doAction() + EndTreatment() / No : Continue.

is there a button on point P for NiftyDisplay2 ? Yes : doAction() + EndTreatment() / No : Continue.



simpleApplication part :

click received one point P




In the new version, the treatment is ended if there is something to do on NiftyDisplay0.

The whole new system is better, but what I wish is :



guiViewPort : { NiftyDisplay0, NiftyDisplay1, NiftyDisplay2 };

And :

click on point P(X,Y)

guiViewPort part :

is there a button on point P for NiftyDisplay2 ? Yes : doAction() + EndTreatment() / No : Continue.

is there a button on point P for NiftyDisplay1 ? Yes : doAction() + EndTreatment() / No : Continue.

is there a button on point P for NiftyDisplay0 ? Yes : doAction() + EndTreatment() / No : Continue.



simpleApplication part :

click received one point P

erm, may I suggest to use a single NiftyDisplay and a single screen instead? :slight_smile:



Creating elements (which includes layer!) now dynamically from java has become much easier now with the Nifty 1.3 Builder pattern. The new controls-example project on the Nifty blog uses this feature exclusivly (No xml involved at all!) To switch between the individual dialogs in the demo I simply hide/show the dialog elements (which are custom controls, also being build inside java! :D) which works pretty well!



Maybe take a look at the source of this project which is available in svn? I think it might be less troublesome…

Hi,

Thanks for the answer.



Unfortunatly, I think it might not work :



I can’t give up on the XML :

Well, in fact I’m really used to creating GUI via XML. Before trying to create my own game with some friends, I was developping GUI for Neverwinter Nights 2 modules.



I actually think it’s a good think to separate how the GUI behaves and how it looks.

I try to do my GUI in XML format as much as I can.



Obviously, the most complex parts will be handed in JAVA, but I want my game to be ‘customisable’ by anyone who wants to try ( like changing the background of the windows, making one button wider, etc… )



I wish to separate each sheet and not having only one controller for all of it :

The reason behind it is that depending of the place you are in the game, the available sheet will change. ( Each place has its own XML, in which I define which sheets are available, the 3D model of the battleground, the peoples inside it, etc… )

Example :



Place : intro

[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<view background=“Menu.dds” >

<sheets>

<sheet file=“sheet_start.xml” />

</sheets>

<events/>

</view>

[/xml]

Place : Game over

[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<view background=“Menu.dds” >

<sheets>

<sheet file=“gameOver.xml” />

</sheets>

<events/>

</view>

[/xml]

Place : firstbattle

[xml]

<view background=“BrightSky.dds” >

<sheets>

<sheet file=“enteringTown.xml” />

<sheet file=“sheet_start.xml” />

</sheets>

<events/>

<scene zip=“assets/Scenes/a0K_ArnanStart.zip” scene=“a0K_ArnanStart_main.j3o”

width=“25” depth=“25” >

<camera>

<startingPoint x=“20” y=“10” z=“0” />

<lookAtPoint x=“12” z=“12” />

<range/>

</camera>



<battle>

[…]

[/xml]



I’ve seen the improvment of Builder classes. Looks great, and I will definetely use them for some of my complex GUI ( Like for displaying items ), but I don’t think I will use them for the simple ones.



I can’t put all my screen element inside a single XML :

The example I gave in my previous post is perhaps a bad one. In fact, most of the sheet take only a small portion of the screen, and many are meant to be displayed together.

I can’t have only one at a time.



There may still be a solution

I may convert all my current sheets to big controls.

If I have undertood correctly, -layer- are in fact the same as -panel childLayout=“overlay”-

I think it’s possible to convert all my screen to controls but there is some drawbacks :


  • I didn’t test in Nifty1.3 but in Nifty1.2 controls are more sensitive that screen :

    If a controls is not correctly written, Nifty don’t wan’t to init itself.

    Until now, since I used different Nifty display, it didn’t give problem. Only the one screen that was not correctly written was not displayed.

    If I transform all my screen to controls. On wrong move and nothing works anymore :frowning:


  • Well, I don’t know if you can do exacly the same thing with a ScreenControlller and with a Controller. ( But on that point you’re far more knowledgeable than me )


  • Seeing the number of sheets I have, it will take me a month I think to change all of them xD



    To conclude

    It’s not like I am really stuck. I might be able to manage something if this “bug” can’t be corrected.

    But I will be really gratefull if it can, it will save me a huge amount of time :slight_smile:



    From my analysis, the problem comes from the interaction between Nifty Displays and JME3.

    The Nifty display that was first added, is treated in first.

    But this NiftyDisplay is the one on the back of the screen. All Nifty Display that have been added after it, are one top of it and should be treated before.

    It’s a FIFO, but it should be a FILO.



    I stay on my positions because I really think it’s only a list that have to be read in reverse. ( But, I don’t know on wich side it is. Yours or Momoko Fan )

I believe it is fundamental to the InputManager that it calls listeners in the order they were added. The fact that the listeners are multiple layers of a screen isn’t really its problem… and it would break a whole bunch of other things (my own app included) if it suddenly started delivering events backwards. I make sure to register my raw listener first so that I get to events before, say, nifty gets them.



So, to get the JME3 nifty adapter to play nice, it would have to register one listener and then keep track of all of the different instances you’ve created so that it could call them ‘backwards’. That seems like a lot of work to me for what in the long run (at least I hope) is an isolated use-case. After all, personally, I hope what you are trying to do becomes easier without the extra work.



I don’t even know how hard it would be to hack around this from your end as I haven’t looked at the exact code that registers the listeners.

Well, I don’t really know how it works.

I don’t even know if Nifty listener have their own management or if they are treated the same way as the other listener.

If the Nifty listener is managed the same way as the other, it may be problematic xD

I haven’t think of how it would impact the other project ( Thinking I was the only weird guy to play with multiple Nifty display in such intensity )



I still think there is a problem : When I have a button in the middle of my screen, I expect it to be the one toggled when I click on it.

My solution is perhaps not the good one, perhaps the fix should be : The first Nifty display registered should be the one in the top of the screen ( even if it won’t help me xD )



I think there will be few people that will try to play with Nifty Display like me. But I’m sure you will have a bunch of other people who will ask :

" I don’t understand, I have loaded my two XML files for my games, but the one that is called in the one in the back"



Even if Nifty 1.3 now encourages the use of JAVA to create the GUI, XML still is an option, and I’m sure I’m not the only want who will want to have at least two XML files for their GUI. :slight_smile:

As far as I understand it, nothing keeps you from having as many XML files as you want… but nifty wants to display only one screen at a time. I thought that was the nature of your dilemma.



(Actually, I just tested the multi-XML file thing… it works but it’s not at all as nice as I wanted it to be.:slight_smile: Each successive XML loaded blows away the last definition loaded… so you’d have to manage your screen-XML relationship… but I guess you are already doing that. Actually… I see how that would be a problem if you wanted a layer per XML or something.)

Yes, my problem is that I wish to have multiple XML file loaded at the same time.

( Like I was doing on my previous projects on NWN2. One for the character sheet, one for the health bar, etc…)



To do that, I create multiple Nifty Display. And that is the source of the problem. The last one loaded appears on the top of my screen, even if it is the last one treated.


you’d have to manage your screen-XML relationship… but I guess you are already doing that.

Yep. I'm pretty fond of my system, that's why I'm reluctant to destroy it xD
But the more I speak abou it, the more I think the best way is to change all my ScreenController to Controller and add all my Sheet inside the same Nifty Display as controls.
( That way I will be able to decide which one will be one top for example )

It will take me some time to change all my current sheets :( .
But it's still better to do it now, than staying on something that I can't control totally and find another problem in 5 month and having to change all the system at that time xD

By the way, you have a third way to fix the "bug". Just don't allow more than one Nifty Display to be added :D

Edit :
Now that I'm on it. How do you define the resolution you want for your screen inside a XML ? :P

In fact, it was easier than I thought.

It took me four day to switch ( Including bug fixes )



My one month prediction was a little off xD

Case solved.