Nifty XML Geometries? (27 posts)

  • Profile picture of amt222 amt222 said 3 months, 4 weeks ago:

    Hello, first time post here,

    I’m trying to add a spherical geometry integrated into my HUD via XML as a control (such that the sphere’s properties, such as size and color, can be changed at runtime). Is there any way to do so?

    Thanks,

    Amtie

  • Profile picture of amt222 amt222 said 3 months, 4 weeks ago:

    My opening post was due to following paragraph in this webpage: Jme3: Advanced tutorial: HUDs

    Displaying Geometries in the HUD

    It is technically possible to attach Quads and 3D Geometries to the HUD. They show up as flat, static GUI elements. Note that if you use a lit Material, you must add a light to the guiNode. Also remember that size units are pixels in the HUD (a 2-wu cube is displayed tiny 2 pixels wide!).

  • Profile picture of glaucomardano glaucomardano252p said 3 months, 4 weeks ago:

    Yes u can. Make you control an AppState and attach it to the state manager. Then your control will have access to the scenegraph. Read the Nifty Scenarios tutorial in jmp manual (F1).

  • Profile picture of amt222 amt222 said 3 months, 4 weeks ago:

    @glaucomardano said:
    Make you control an AppState and attach it to the state manager. Then your control will have access to the scenegraph. Read the Nifty Scenarios tutorial in jmp manual (F1).

    The control, you mean the actual control in the XML (like buttons, checkboxes, etc?), or are you referring to the ScreenController? My ScreenController (which controls multiple screens, if thats of any useful information to you) already extends AbstractAppState and is attached to the StateManager like so:

    	@Override
    	public void initialize(AppStateManager stateManager, Application app) {
    		super.initialize(stateManager, app);
    		this.app = (SimpleApplication)app;
    	}

    Is there an online version of the tutorial? I’m using Eclipse with a snapshot release of the jm3 libraries. Unless you’re talking about this page:http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:nifty_gui_scenarios

    I am also unsure of how to use (or even reference) the sceneGraph you are referring to.

    Thanks

  • Profile picture of glaucomardano glaucomardano252p said 3 months, 4 weeks ago:

    No. I meant the control definitions, as yourself said before, you create a control that implements NiftyControl (like the other nifty control definitions as well) and implement AppState on it, and then attach it to the appStateManager. Then you’ll have access to app, and consequently you’ll have access to the scene graph as well. Then you can create your geometries inside your controls and attach them to the root node.

  • Profile picture of amt222 amt222 said 3 months, 4 weeks ago:

    Alright, thanks for your help. I’ll try that.

  • Profile picture of amt222 amt222 said 3 months, 3 weeks ago:

    Hello again,

    I’m unsure on how to implement all of the inherited methods from AppState and NiftyControl. And whats worse is that the only custom-control tutorial (http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:loading_screen) doesn’t use AppState nor NiftyControl.

    I’d have extended LabelControl but apparently that’s been deprecated…

    An example of the Java class would be really helpful, if you can spare the time for one. I’d appreciate it. :)

  • Profile picture of glaucomardano glaucomardano252p said 3 months, 3 weeks ago:

    Well, you don’t need to implement LabelControl, and actually there’s no tutorial for creating custom control, but there’s a tutorial about creating a progress bar control definition. I learnet how to create my custom controls by checking the nifty source code, then you’ll have to do the same. It’s not needed to implement, LabelControl, implement NiftyControl and put the nifty controls there (label, image…). Tonight I can show you some examples that I have in my game.

  • Profile picture of amt222 amt222 said 3 months, 3 weeks ago:

    Thank you! :D

  • Profile picture of amt222 amt222 said 3 months, 3 weeks ago:

    Have you managed to get the examples yet?

  • Profile picture of cghislai cghislai10p said 3 months, 3 weeks ago:

    I would look into the nifty-default controls to see how other controls are made.
    You will need: a xml control definition (should only contain a panel in your case i assume), A control Controller, BuildMyControl class to build the actual control instance, and a ControlBuilder class to use the java control builder (might not be needed if you only use xml). Again look in default controls for some examples (Button is a simple comprehensible one).

    I’m not sure about the AppState method however. I think nifty will try to get an instance of your controller using an empty constructor. So you will have to figure out how to get access to the scenegraph from your controller. (I’m thinking of some static field somewhere but there has to be better solutions)

    In your controller bind method, construct the sphere. Check your control’s panel bounds to see where you should put it and attach it to the guiNode. I guess that would work although i never tested. If you need to update it each frame, you can create an effect for this purpose.

  • Profile picture of glaucomardano glaucomardano252p said 3 months, 3 weeks ago:

    @amt222 said:
    Have you managed to get the examples yet?

    Oh sorry. I forgot xD . Tonight ;) .

  • Profile picture of glaucomardano glaucomardano252p said 3 months, 3 weeks ago:

    Here is it ^^

    progress-bar.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty-controls>
        <controlDefinition name = "progressBar" controller = "kinetrax.nifty.control.progressbar.ProgressBarControl">
            <image id="progressBarBorder" filename="Interface/Skins/ProgressBar/border.png" childLayout="horizontal"
                   imageMode="resize:15,2,15,15,15,2,15,2,15,2,15,15">
                <image id="progressBarInner" x="0" y="0" filename="$image" width="100%" height="100%"
                       imageMode="resize:15,2,15,15,15,2,15,2,15,2,15,15" childLayout="" valign="bottom">
                </image>
            </image>
        </controlDefinition>
    </nifty-controls>
    

    controls.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty-controls>
        <useControls filename="Interface/Controls/ProgressBar/progress-bar.xml" />
        <useControls filename="Interface/Controls/RhythmTrack/rhythm-track.xml" />
        <useControls filename="Interface/Controls/MoveBar/move-bar.xml" />
        <useControls filename="Interface/Controls/TrackSelect/track-select.xml" />
        <useControls filename="Interface/Controls/Track/track.xml" />
    </nifty-controls>
    

    ProgressBar.java

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package kinetrax.nifty.control.progressbar;
    
    import de.lessvoid.nifty.controls.NiftyControl;
    
    /**
     *
     * @author Glauco Márdano
     */
    public interface ProgressBar extends NiftyControl {
    
        public void setProgress(float progress);
    
        public float getProgress();
    
        public void setDirection(String direction);
    }
    

    ProgressBarControl.java

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package kinetrax.nifty.control.progressbar;
    
    import de.lessvoid.nifty.Nifty;
    import de.lessvoid.nifty.elements.Element;
    import de.lessvoid.nifty.layout.manager.HorizontalLayout;
    import de.lessvoid.nifty.layout.manager.VerticalLayout;
    import de.lessvoid.nifty.screen.Screen;
    import de.lessvoid.nifty.tools.SizeValue;
    import de.lessvoid.xml.xpp3.Attributes;
    import java.util.Properties;
    import kinetrax.nifty.control.KinetraxController;
    
    /**
     *
     * @author Glauco Márdano
     */
    public class ProgressBarControl extends KinetraxController implements ProgressBar {
    
        private float progressParam;
        private String directionParam;
        private Element progressBarInner;
    
        @Override
        public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
            super.bind(nifty, screen, element, parameter, controlDefinitionAttributes);
        }
    
        @Override
        protected void initializeParameters(Properties parameter) {
            progressBarInner = getElement().findElementByName("progressBarInner");
            setDirection(parameter.getProperty("direction"));
            setProgress(Float.parseFloat(parameter.getProperty("progress")));
            setChildLayout(directionParam);
            progressBarInner.getParent().layoutElements();
        }
    
        public void setProgress(float progress) {
            assert progress >= 0f && progress <= 1f : "progress out of range " + progress;
            progressParam = progress;
            final int MIN_WIDTH = 32;
            final int MIN_HEIGHT = 32;
            if (directionParam.equals("horizontal")) {
                int pixelWidth = (int) (MIN_WIDTH + (progressBarInner.getParent().getWidth() - MIN_WIDTH) * progress);
                progressBarInner.setConstraintWidth(new SizeValue(pixelWidth + "px"));
            }
            if (directionParam.equals("vertical")) {
                int pixelHeight = (int) (MIN_HEIGHT + (progressBarInner.getParent().getHeight() - MIN_HEIGHT) * progress);
                progressBarInner.setConstraintHeight(new SizeValue(pixelHeight + "px"));
            }
            progressBarInner.getParent().layoutElements();
        }
    
        public float getProgress() {
            return progressParam;
        }
    
        public void setDirection(String direction) {
            assert direction.equals("horizontal") || direction.equals("vertical") : "direction unrecognized " + direction;
            this.directionParam = direction;
        }
    
        private void setChildLayout(String direction) {
            if (direction.equals("horizontal")) {
                progressBarInner.setLayoutManager(new VerticalLayout());
            }
            if (direction.equals("vertical")) {
                progressBarInner.setLayoutManager(new HorizontalLayout());
            }
        }
    
        public void update(float tpf) {
        }
    }
    

    KinetraxController.java

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package kinetrax.nifty.control;
    
    import com.jme3.app.Application;
    import com.jme3.app.state.AppState;
    import com.jme3.app.state.AppStateManager;
    import com.jme3.renderer.RenderManager;
    import de.lessvoid.nifty.Nifty;
    import de.lessvoid.nifty.controls.AbstractController;
    import de.lessvoid.nifty.elements.Element;
    import de.lessvoid.nifty.input.NiftyInputEvent;
    import de.lessvoid.nifty.screen.Screen;
    import de.lessvoid.xml.xpp3.Attributes;
    import java.util.Properties;
    import kinetrax.app.KinetraxApp;
    import kinetrax.audio.AudioManager;
    
    /**
     *
     * @author Glauco Márdano
     */
    public abstract class KinetraxController extends AbstractController implements AppState {
    
        private Nifty nifty;
        private Screen screen;
        private Element element;
        private Properties parameter;
        private Attributes controlDefinitionAttributes;
        private KinetraxApp app;
        private AppStateManager stateManager;
        private boolean initialized;
        private boolean enabled = true;
        private AudioManager audioManager;
    
        public KinetraxController() {
            super();
        }
    
        public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
            this.nifty = nifty;
            this.screen = screen;
            this.element = element;
            this.parameter = parameter;
            this.controlDefinitionAttributes = controlDefinitionAttributes;
            initializeParameters(parameter);
        }
    
        protected abstract void initializeParameters(Properties parameter);
    
        public void onStartScreen() {
        }
    
        public boolean inputEvent(NiftyInputEvent inputEvent) {
            return false;
        }
    
        public Attributes getControlDefinitionAttributes() {
            return controlDefinitionAttributes;
        }
    
        public Nifty getNifty() {
            return nifty;
        }
    
        public void setNifty(Nifty nifty) {
            this.nifty = nifty;
        }
    
        @Override
        public Element getElement() {
            return element;
        }
    
        public Properties getParameter() {
            return parameter;
        }
    
        public Screen getScreen() {
            return screen;
        }
    
        public void setScreen(Screen screen) {
            this.screen = screen;
        }
    
        public void initialize(AppStateManager stateManager, Application app) {
            initialized = true;
            this.app = (KinetraxApp) app;
            this.stateManager = stateManager;
            audioManager = this.app.getAudioManager();
        }
    
        public void cleanup() {
            initialized = false;
        }
    
        public boolean isInitialized() {
            return initialized;
        }
    
        public void stateAttached(AppStateManager stateManager) {
        }
    
        public void stateDetached(AppStateManager stateManager) {
        }
    
        public void render(RenderManager rm) {
        }
    
        public void postRender() {
        }
    
        @Override
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    
        public KinetraxApp getApp() {
            return app;
        }
    
        public AppStateManager getStateManager() {
            return stateManager;
        }
    
        public void setStateManager(AppStateManager stateManager) {
            this.stateManager = stateManager;
        }
    
        public AudioManager getAudioManager() {
            return audioManager;
        }
    }
    

    Usage in StartScreen.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty xmlns="http://nifty-gui.sourceforge.net/nifty-1.3.xsd&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd"&gt;
      <!-- +++++++++++++++++++++++++++++++++++++++ -->
      <!-- start screen -->
      <!-- +++++++++++++++++++++++++++++++++++++++ -->
        <useStyles filename="Interface/Styles/styles.xml" />
        <useControls filename="nifty-default-controls.xml" />
        <useControls filename="Interface/Controls/controls.xml" />
        <screen id="startScreen" controller="kinetrax.nifty.control.screen.start.StartScreenControl">
            <layer id="startLoadingLayer" childLayout="horizontal">
                <panel height="10%"/>
                <panel id = "startLoadingPanel" childLayout="vertical" align="center" valign="center" height="32px" width="80%">
                    <control image="Interface/Skins/ProgressBar/inner-orange.png" id="startLoadingBar" name="progressBar" align="center" valign="center" width="100%" height="100%" progress="0f" direction="horizontal" progresstext="Loading..."/>
                </panel>
                <panel height="10%"/>
            </layer>
            <layer id="startLoadingTextLayer" childLayout="horizontal">
                <panel height="10%"/>
                <panel id = "startLoadingTextPanel" childLayout="center" align="center" valign="center" height="32px" width="80%">
                    <control id="startLoadingProgressText" text="Loading..." name="label" align="center" valign="center" width="100%"/>
                </panel>
                <panel height="10%"/>
            </layer>
        </screen>
    </nifty>
    

    -Regards

  • Profile picture of amt222 amt222 said 3 months, 3 weeks ago:

    Thanks! I’ll try it soon.

  • Profile picture of amt222 amt222 said 3 months, 2 weeks ago:

    Hello again,

    Is there something missing from what you’ve posted? Because my equivalent of your ProgressBarControl class’ initializeParameters(Properties parameter) method isn’t been called. Oh, I’d just like to mention that I haven’t been working very long with jme or nifty. So I’m not very familiar with the API. However, I have done quite a few of the tutorials, and looked at all relevant tutorials (e.g. the nifty gui ones).

    Here’s all the equivalent parts:

    geometry-image.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty-controls>
    	<controlDefinition name="geometryImage" controller="ui.GeometryImageControl">
    		<panel id="panel" backgroundColor="#f00f">
    
    		</panel>
    	</controlDefinition>
    </nifty-controls>

    controls.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty-controls>
    	<useControls filename="Gui/geometry-image.xml" />
    </nifty-controls>

    GeometryImage.java

    package ui;
    
    import com.jme3.scene.Geometry;
    
    import de.lessvoid.nifty.controls.NiftyControl;
    
    public interface GeometryImage extends NiftyControl {
    
    	public void setGeometry(Geometry geometry);
    
    	public Geometry getGeometry();
    
    }

    GeometryImageControl.java

    package ui;
    
    import java.util.Properties;
    
    import com.jme3.material.Material;
    import com.jme3.math.ColorRGBA;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.shape.Sphere;
    
    import de.lessvoid.nifty.Nifty;
    import de.lessvoid.nifty.elements.Element;
    import de.lessvoid.nifty.screen.Screen;
    import de.lessvoid.xml.xpp3.Attributes;
    
    public class GeometryImageControl extends StarMapController implements GeometryImage {
    
    	private Geometry geometry;
    
    	private Element geometryImage;
    
    	@Override
    	public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
    		super.bind(nifty, screen, element, parameter, controlDefinitionAttributes);
    	}
    
    	@Override
    	public void update(float arg0) {}
    
    	@Override
    	public void setGeometry(Geometry geometry) {
    		this.geometry = geometry;
    		guiNode.attachChild(geometry);
    
    		//float x = geometryImage.getConstraintX().getValue(0.5f);
    		//float y = geometryImage.getConstraintY().getValue(0.5f);
    		geometry.setLocalTranslation(1, 1, 1);
    
    		geometryImage.getParent().layoutElements();
    	}
    
    	@Override
    	public Geometry getGeometry() {
    		return geometry;
    	}
    
    	@Override
    	protected void initializeParameters(Properties parameter) {
    		System.out.println("TEST TWO");
    		geometryImage = getElement().findElementByName("geometryImage");
    		float size = Float.parseFloat(parameter.getProperty("size"));
    
    		float r = Float.parseFloat(parameter.getProperty("colorR"));
    		float g = Float.parseFloat(parameter.getProperty("colorG"));
    		float b = Float.parseFloat(parameter.getProperty("colorB"));
    		float a = Float.parseFloat(parameter.getProperty("colorA"));
    		ColorRGBA color = new ColorRGBA(r, g, b, a);
    
    		Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    		mat.setColor("Color", color);
    
    		Geometry star = new Geometry("starImage", new Sphere(30,30, size));
    		star.setMaterial(mat);
    
    		setGeometry(star);
    	}
    
    }

    StarMapController.java

    package ui;
    
    import java.util.Properties;
    
    import com.jme3.app.Application;
    import com.jme3.app.state.AppState;
    import com.jme3.app.state.AppStateManager;
    import com.jme3.asset.AssetManager;
    import com.jme3.renderer.RenderManager;
    import com.jme3.scene.Node;
    
    import de.lessvoid.nifty.Nifty;
    import de.lessvoid.nifty.controls.AbstractController;
    import de.lessvoid.nifty.elements.Element;
    import de.lessvoid.nifty.input.NiftyInputEvent;
    import de.lessvoid.nifty.screen.Screen;
    import de.lessvoid.xml.xpp3.Attributes;
    
    public abstract class StarMapController extends AbstractController implements AppState {
    
    	private Nifty nifty;
    	private Screen screen;
    	private Element element;
    	private Properties parameter;
    	private Attributes controlDefinitionAttributes;
    	private UIView app;
    	private AppStateManager stateManager;
    	private boolean initialized;
    	private boolean enabled = true;
    
    	protected Node guiNode;
    	protected AssetManager assetManager;
    
    	public StarMapController() {
    		super();
    		System.out.println("TEST TEST TEST");
    	}
    
    	@Override
    	public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
    		this.nifty = nifty;
    		this.screen = screen;
    		this.element = element;
            this.parameter = parameter;
            this.controlDefinitionAttributes = controlDefinitionAttributes;
            initializeParameters(parameter);
    	}
    
    	protected abstract void initializeParameters(Properties parameter);
    
    	@Override
    	public void onStartScreen() {}
    
    	@Override
    	public boolean inputEvent(NiftyInputEvent inputEvent) {
    		return false;
    	}
    
    	@Override
    	public void cleanup() {
    		initialized = false;
    	}
    
    	@Override
    	public void initialize(AppStateManager stateManager, Application app) {
    		initialized = true;
    		this.app = (UIView)app;
    		this.assetManager = this.app.getAssetManager(); // this method is not running!
    		this.stateManager = stateManager; System.out.println("TEST TEST TEST TEST TEST TEST: " + app.getGuiViewPort().getScenes().get(0).getName());
    	}
    
    	@Override
    	public boolean isInitialized() {
    		return initialized;
    	}
    
    	@Override
    	public void postRender() {}
    
    	@Override
    	public void render(RenderManager rm) {}
    
    	@Override
    	public void stateAttached(AppStateManager stateManager) {}
    
    	@Override
    	public void stateDetached(AppStateManager stateManager) {}
    
    }

    Usage in gui.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <nifty xmlns="http://nifty-gui.sourceforge.net/nifty.xsd&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty.xsd"&gt;
    
    	<useStyles filename="nifty-default-styles.xml" />
    	<useControls filename="nifty-default-controls.xml" />
    	<useControls filename="Gui/controls.xml" />
    
    	<screen id="start" controller="ui.UIScreenController">
    		<layer id="background" backgroundColor="#000f" childLayout="center">
    			<image filename="Textures/background.png"></image>
    		</layer>
    		<layer id="foreground" backgroundColor="#0009" childLayout="vertical">
    
    		</layer>
    	</screen>
    
    	<screen id="starview"  controller="ui.UIScreenController">
    		<layer id="background">
    			<!-- None -->
    		</layer>
    		<layer id="foreground" childLayout="horizontal">
    			<panel id="panel_left" width="250px" height="400px" childLayout="vertical" backgroundColor="#0009">
    
    				<panel id="panel_system_name" width="100%" height="20px" childLayout="center">
    					<control id="starLabel" name="textfield" color="#ffff" text="123" width="100%" height="100%" />
    				</panel>
    
    				<panel id="panel_main_system_info" width="100%" height="120px" childLayout="horizontal">
    
    					<!-- Planet/star size will range from 80px to 60px (size 10 to size 1) -->
    					<panel id="panel_system_star" width="120px" height="100%" childLayout="center">
    						<control id="geometryImage" name="uiStar" width="100%" height="100%" size="70"
    									colorR="255" colorG="255" colorB="255" colorA="127"/>
    					</panel>
    				</panel>
    
    			</panel>
    		</layer>
    	</screen>
    
    </nifty>