Project: Tinker an xml editor with JME3?

Hello!

A few days ago I was madly wondering if I could do an XML editor in 3D with Lemur and JME. Already clear - this is not a game. Today a (splitt-) picture of my test. Now I still have to incorporate all of the inputs.

Does anyone have an idea how I can implement the popup menu in Lemur as sensibly as possible?

7 Likes

You can use the built-in PopupState from Lemur:

2 Likes

Thank you very much, it works great.

(Lemur 1.15.0 + Lemur proto-1.12.0)
My preliminary implementation:

        PopUpMenu pm = new PopUpMenu();
        pm.scale(1.8f);
        pm.setLocalTranslation(400, 600, 100);
          // Make some test data for the list. 
        for( int i = 0; i < 10; i++ ) {
            pm.addMenuItem("Menu item " + (i+1));
        }
        pm.show();
package com.simsilica.lemur;

import com.simsilica.lemur.component.ChangeItemListener;
import com.simsilica.lemur.component.MenuItem;
import com.simsilica.lemur.core.VersionedList;
import com.simsilica.lemur.event.PopupState;
import java.util.Iterator;

/**
 *
 * @author Janusch Rentenatus
 */
public class PopUpMenu extends Container implements ChangeItemListener {

    private VersionedList<MenuItem> menuList;
    private boolean uptodate;

    public PopUpMenu() {
        menuList = new VersionedList<>();
        uptodate = false;
    }

    public void addMenuItem(MenuItem item) {
        uptodate = false;
        menuList.add(item);
    }

    public void addMenuItem(String itemText) {
        uptodate = false;
        menuList.add(new MenuItem(itemText));
    }

    public Iterator<MenuItem> itemIterator() {
        return menuList.iterator();
    }

    public boolean removeMenuItem(MenuItem item) {
        uptodate = false;
        return menuList.remove(item);
    }

    @Override
    public void itemChanged(MenuItem item) {
        uptodate = false;
    }

    protected void rebuild() {
        clearChildren();
        for (MenuItem menuItem : menuList) {
            Button clickMe = addChild(new Button(menuItem.getItemText()));
            clickMe.addClickCommands(menuItem.getClickCommands());
            clickMe.setBackground(null);
        }
        uptodate = true;
    }

    public void showMenu() {
        PopUpMenu pm = new PopUpMenu();
        pm.scale(1.8f);
        // Make some test data for the list. 
        for (int i = 0; i < 10; i++) {
            pm.addMenuItem("Menu item " + (i + 1));
        }
        pm.show();

        final Vector2f click2d = app.getInputManager().getCursorPosition();
        float width = app.getCamera().getWidth();
        
        Vector3f size = pm.getPreferredSize();
        pm.setLocalTranslation(
                Math.min(click2d.x, width - size.x*1.8f ),
                Math.max(click2d.y, size.y*1.8f), 
                100);
    }

}
package com.simsilica.lemur.component;

import java.util.EventListener;

/**
 *
 * @author Janusch Rentenatus
 */
public interface ChangeItemListener extends EventListener {
    
    public void itemChanged(MenuItem item);
    
}
package com.simsilica.lemur.component;

import com.simsilica.lemur.Button;
import com.simsilica.lemur.Command;
import java.util.EventListener;

/**
 *
 * @author Janusch Rentenatus
 */
public class MenuItem {

    private String itemText;
    private Command<? super Button> clickCommands;

    public MenuItem(String itemText) {
        this.itemText = itemText;
        this.clickCommands = printlnClickCommands();
    }

    public MenuItem(String itemText, Command<? super Button> clickCommands) {
        this.itemText = itemText;
        this.clickCommands = clickCommands;
    }

    public Command<? super Button> printlnClickCommands() {
        return (new Command<Button>() {
            @Override
            public void execute(Button source) {
                System.out.println(itemText + ": The world is yours.");
            }
        });
    }

    public String getItemText() {
        return itemText;
    }
    
    public void setItemText(ChangeItemListener listener,  String itemText) {
        this.itemText = itemText;
        listener.itemChanged(this);
    }
    
    

    public Command<? super Button> getClickCommands() {
        return clickCommands;
    }
    
    public void setClickCommands(ChangeItemListener listener,  Command<? super Button> clickCommands){
        this.clickCommands=clickCommands;
        listener.itemChanged(this);
    }

}

so far, so good, basic functionality is …

the text fields on the right are in the rootNode instead of the guiNode. If only someone tells me how I can direct the focus for the input there!

You mean set the focus? Same as anywhere else… you set the focus to that component.

Lemur doesn’t care what node it’s in.

1 Like

Selection in TextField, popupmenu, splitter, …
Next Video:

2 Likes

Update:

2 Likes

I’m currently working on main menu.
To do: Load, save, new … that will be something.

Fixed problem with rotated SelTextField.
Not really needed here (yet). But it’s reassuring.

Dropped the Lemur extension on GIT:

1 Like

looks really interesting . can you post a short clip demonstrating it?

In a hurry, check out the videos above.

1 Like

By the way, small demo and small optimizations (SelTextField only) are pushed:


Oh yes, the pop-up menu is automatically included! Can also be expanded with your own points.

3 Likes

Hi!

After I invented an explainable AI, presented my idea to actuaries and tinkered with a prototype for xAI,
I would like to upload a new video for this XML project today.

Now I have implemented the arrow keys. Without shift: line up and down, with shift: entry same deep up and down. Selected entry is focused. The angle of the camera is converted.

Thanks for watching.

3 Likes

Congrats on the project, @JaRe :melting_face: