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:

Hi!

It’s been so long since I continued working on this project. I’ve been busy for a year now implementing a really explainable AI that sucks.

Back to the XML project:

I would also like to use my editor to tinker with a model generation at some point.

Now I’m working on a popup list picker. Here in the video class names of Lemur. Now I ‘just’ have to finish the search field…

Edit: The filter is today done. Wildcard “*” and “?” can be used. There is an imaginary “*” in front of each uper case letter, except the first character in the filter.

To render the ListBox I also use my own Sel Text Field (based on Aufricer solutioin) with multiselection. Marking has long been a grandient and not just monochromatic.

2 Likes