package Savage.Tools.HeadsUpDisplays;

import org.web3d.x3d.jsail.Core.*;
import org.web3d.x3d.jsail.EnvironmentalSensor.*;
import org.web3d.x3d.jsail.fields.*;
import org.web3d.x3d.jsail.Geometry3D.*;
import org.web3d.x3d.jsail.Grouping.*;
import org.web3d.x3d.jsail.Interpolation.*;
import org.web3d.x3d.jsail.Lighting.*;
import org.web3d.x3d.jsail.Navigation.*;
import org.web3d.x3d.jsail.Scripting.*;
import org.web3d.x3d.jsail.Shape.*;
import org.web3d.x3d.jsail.Time.*;

// Javadoc metadata annotations follow, see below for X3DJSAIL Java source code.
/**
 * <p> Example world using an adjustable Heads-Up Display (HUD) or control panel. The panel always appears in the same position in the brower's window, independent of view point. The HUD can be dragged around the window by grabbing onto the border and sliding. </p>
 <p> Related links: Catalog page <a href="../../../../Tools/HeadsUpDisplays/HudControlPanelExampleIndex.html" target="_blank">HudControlPanelExample</a>,  source <a href="../../../../Tools/HeadsUpDisplays/HudControlPanelExample.java">HudControlPanelExample.java</a>, <a href="https://www.web3d.org/x3d/content/examples/X3dResources.html" target="_blank">X3D Resources</a>, <a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">X3D Scene Authoring Hints</a>, and <a href="https://www.web3d.org/x3d/content/X3dTooltips.html" target="_blank">X3D Tooltips</a>. </p>
	<table style="color:black; border:0px solid; border-spacing:10px 0px;">
        <caption>Scene Meta Information</caption>
		<tr style="background-color:silver; border-color:silver;">
			<td style="text-align:center; padding:10px 0px;"><i>meta tags</i></td>
			<td style="text-align:left;   padding:10px 0px;">&nbsp; Document Metadata </td>
		</tr>

		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> title </i> </td>
			<td> <a href="../../../../Tools/HeadsUpDisplays/HudControlPanelExample.x3d">HudControlPanelExample.x3d</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> description </i> </td>
			<td> Example world using an adjustable Heads-Up Display (HUD) or control panel. The panel always appears in the same position in the brower's window, independent of view point. The HUD can be dragged around the window by grabbing onto the border and sliding. </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> creator </i> </td>
			<td> Leonard Daly </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> translator </i> </td>
			<td> Dan Kucik </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> created </i> </td>
			<td> 1999 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> translated </i> </td>
			<td> 8 June 2003 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> modified </i> </td>
			<td> 28 November 2019 </td>
		</tr>
		<tr style="color:red">
			<td style="text-align:right; vertical-align: text-top;"> <i> error </i> </td>
			<td> HUD does not sit still when navigating </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="http://www.realism.com/Web3D/Examples/examples.cgi?ID=5" target="_blank">http://www.realism.com/Web3D/Examples/examples.cgi?ID=5</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> rights </i> </td>
			<td> This code may be reused in part or total. Please include this paragraph when it is used. Copyright 1999, Leonard Daly #**************** </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> Image </i> </td>
			<td> <a href="http://www.realism.com/vrml/Example/HUD/CP.gif" target="_blank">http://www.realism.com/vrml/Example/HUD/CP.gif</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> subject </i> </td>
			<td> Heads-up display example </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> Original VRML File: <a href="http://www.realism.com/vrml/Example/HUD/HUD.wrl" target="_blank">http://www.realism.com/vrml/Example/HUD/HUD.wrl</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> identifier </i> </td>
			<td> <a href="https://www.web3d.org/x3d/content/examples/Savage/Tools/HeadsUpDisplays/HudControlPanelExample.x3d" target="_blank">https://www.web3d.org/x3d/content/examples/Savage/Tools/HeadsUpDisplays/HudControlPanelExample.x3d</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> generator </i> </td>
			<td> Vrml97ToX3dNist, <a href="http://ovrt.nist.gov/v2_x3d.html" target="_blank">http://ovrt.nist.gov/v2_x3d.html</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> generator </i> </td>
			<td> X3D-Edit 3.2, <a href="https://www.web3d.org/x3d/tools/X3D-Edit" target="_blank">https://www.web3d.org/x3d/tools/X3D-Edit</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> license </i> </td>
			<td> <a href="../../../../Tools/HeadsUpDisplays/../../license.html">../../license.html</a> </td>
		</tr>
		<tr style="background-color:silver; border-color:silver;">
			<td style="text-align:center;" colspan="2">  &nbsp; </td>
		</tr>
	</table>

	<p>
		This program uses the
		<a href="https://www.web3d.org/specifications/java/X3DJSAIL.html" target="_blank">X3D Java Scene Access Interface Library (X3DJSAIL)</a>.
		It has been produced using the 
		<a href="https://www.web3d.org/x3d/stylesheets/X3dToJava.xslt" target="_blank">X3dToJava.xslt</a>
		stylesheet
	       (<a href="https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/X3dToJava.xslt" target="_blank">version control</a>)
                which is used to create Java source code from an original <code>.x3d</code> model.
	</p>

	* @author Leonard Daly
 */

public class HudControlPanelExample
{
	/** Default constructor to create this object. */
	public HudControlPanelExample ()
	{
	  initialize();
	}

	/** Create and initialize the X3D model for this object. */
	public final void initialize()
	{
            try { // catch-all
  x3dModel = new X3D().setProfile(X3D.PROFILE_IMMERSIVE).setVersion(X3D.VERSION_3_0)
  .setHead(new head()
    .addMeta(new meta().setName(meta.NAME_TITLE      ).setContent("HudControlPanelExample.x3d"))
    .addMeta(new meta().setName(meta.NAME_DESCRIPTION).setContent("Example world using an adjustable Heads-Up Display (HUD) or control panel. The panel always appears in the same position in the brower's window, independent of view point. The HUD can be dragged around the window by grabbing onto the border and sliding."))
    .addMeta(new meta().setName(meta.NAME_CREATOR    ).setContent("Leonard Daly"))
    .addMeta(new meta().setName(meta.NAME_TRANSLATOR ).setContent("Dan Kucik"))
    .addMeta(new meta().setName(meta.NAME_CREATED    ).setContent("1999"))
    .addMeta(new meta().setName(meta.NAME_TRANSLATED ).setContent("8 June 2003"))
    .addMeta(new meta().setName(meta.NAME_MODIFIED   ).setContent("28 November 2019"))
    .addMeta(new meta().setName(meta.NAME_ERROR      ).setContent("HUD does not sit still when navigating"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("http://www.realism.com/Web3D/Examples/examples.cgi?ID=5"))
    .addMeta(new meta().setName(meta.NAME_RIGHTS     ).setContent("This code may be reused in part or total. Please include this paragraph when it is used. Copyright 1999, Leonard Daly #****************"))
    .addMeta(new meta().setName(meta.NAME_IMAGE      ).setContent("http://www.realism.com/vrml/Example/HUD/CP.gif"))
    .addMeta(new meta().setName(meta.NAME_SUBJECT    ).setContent("Heads-up display example"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("Original VRML File: http://www.realism.com/vrml/Example/HUD/HUD.wrl"))
    .addMeta(new meta().setName(meta.NAME_IDENTIFIER ).setContent("https://www.web3d.org/x3d/content/examples/Savage/Tools/HeadsUpDisplays/HudControlPanelExample.x3d"))
    .addMeta(new meta().setName(meta.NAME_GENERATOR  ).setContent("Vrml97ToX3dNist, http://ovrt.nist.gov/v2_x3d.html"))
    .addMeta(new meta().setName(meta.NAME_GENERATOR  ).setContent("X3D-Edit 3.2, https://www.web3d.org/x3d/tools/X3D-Edit"))
    .addMeta(new meta().setName(meta.NAME_LICENSE    ).setContent("../../license.html")))
  .setScene(new Scene()
    .addChild(new WorldInfo().setTitle("HudControlPanelExample.x3d"))
    .addChild(new ExternProtoDeclare("HudControlPanel").setName("HudControlPanel").setAppinfo("Heads Up Display (HUD) Control Panel").setUrl(new String[] {"HudControlPanelPrototype.x3d#HudControlPanel","../../Tools/HeadsUpDisplays/HudControlPanelPrototype.x3d#HudControlPanel","https://www.web3d.org/x3d/content/examples/Savage/Tools/HeadsUpDisplays/HudControlPanelPrototype.x3d#HudControlPanel","../../Tools/HeadsUpDisplays/HudControlPanelPrototype.wrl#HudControlPanel","HudControlPanelPrototype.wrl#HudControlPanel","https://www.web3d.org/x3d/content/examples/Savage/Tools/HeadsUpDisplays/HudControlPanelPrototype.wrl#HudControlPanel"})
      .addField(new field().setName("translation").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("SFVec3f Position of the panel relative to the viewpoint. The X and Y components can be changed by dragging the window around."))
      .addField(new field().setName("orientation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setAppinfo("SFRotation This field should be the object of a ROUTE statement from the orientation_changed event from a ProximitySensor. For some reason the ProximitySensor does not correctly report the current viewpoint when the sensor is located inside of the PROTO."))
      .addField(new field().setName("isOver").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_OUTPUTONLY).setAppinfo("Out - SFBool event is generated when the cursor is over the texture mapped region of the control panel. Set to false when the cursor leaves the texture mapped region."))
      .addField(new field().setName("hitTexCoord_changed").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_OUTPUTONLY).setAppinfo("Out - SFVec2f The X/Y normalized coordinates (S and T) of the cursor location when 'isOver' is true."))
      .addField(new field().setName("borderColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setAppinfo("SFColor The color of the panel border. This is the region that can be used to drag the panel around the screen."))
      .addField(new field().setName("scale").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("SFVec3f Size of the panel. The texture mapped area (see textureMap) is 95% in X and 90% in Y of this size."))
      .addField(new field().setName("position").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setAppinfo("SFVec3f This field should be the object of a ROUTE statement from the position_changed event from a ProximitySensor. See 'orientation' for more details."))
      .addField(new field().setName("textureMap").setType(field.TYPE_MFSTRING).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setAppinfo("MFString The texture map URLs. This is specified in the same manner as the URL field in ImageTexture. The first one that can be loaded is the that is displayed. If this field is not specified then this region of the object is painted white."))
      .addField(new field().setName("touchTime").setType(field.TYPE_SFTIME).setAccessType(field.ACCESSTYPE_OUTPUTONLY).setAppinfo("Out - SFTime The time when a mouse button is released provided that the just prior to release 'isOver' and 'isActive' are true."))
      .addField(new field().setName("isActive").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_OUTPUTONLY).setAppinfo("Out - SFBool A true event is generated when the mouse button is depressed and the cursor is over the texture mapped region. A false event is generated when the button is released or when 'isOver' becomes false.")))
    .addChild(new NavigationInfo("NavInfo").setType(new String[] {"FLY","EXAMINE","ANY"}))
    .addChild(new Viewpoint("SIDE_VP").setDescription("Side View").setJump(false))
    .addChild(new Viewpoint("TOP_VP").setDescription("Top View").setJump(false).setOrientation(1.0,0.0,0.0,-1.57).setPosition(0.0,10.0,0.0))
    .addChild(new Transform("Revolver")
      .addChild(new Transform("Body1").setTranslation(3.0,0.0,0.0)
        .addChild(new PointLight().setColor(0.0,0.0,1.0))
        .addChild(new Shape()
          .setAppearance(new Appearance()
            .setMaterial(new Material().setDiffuseColor(1.0,0.0,0.0).setEmissiveColor(0.0,0.0,1.0).setSpecularColor(0.0,1.0,0.0)))
          .setGeometry(new Sphere().setRadius(0.75))))
      .addChild(new Transform("Body2").setTranslation(-3.0,0.0,0.0)
        .addChild(new SpotLight().setBeamWidth(1.57).setDirection(0.0,-1.0,0.0))
        .addChild(new Shape()
          .setAppearance(new Appearance()
            .setMaterial(new Material().setDiffuseColor(0.0,1.0,1.0)))
          .setGeometry(new Cone().setBottomRadius(0.75).setHeight(1.5)))))
    .addChild(new TimeSensor("Timer1").setCycleInterval(5.0).setLoop(true).setStartTime(1.0))
    .addChild(new TimeSensor("Timer2").setCycleInterval(3.0).setLoop(true).setStartTime(1.0))
    .addChild(new OrientationInterpolator("Spinner").setKey(new double[] {0.0,0.333,0.667,1.0}).setKeyValue(new MFRotation(new double[] {0.0,1.0,0.0,0.0,0.0,1.0,0.0,2.09,0.0,1.0,0.0,4.18,0.0,1.0,0.0,0.0})))
    .addChild(new OrientationInterpolator("Tumble").setKey(new double[] {0.0,0.14,0.28,0.43,0.57,0.71,0.86,1.0}).setKeyValue(new MFRotation(new double[] {0.0,1.0,0.0,0.0,0.0,1.0,0.5,0.898,0.0,0.5,1.0,1.795,0.5,0.0,1.0,2.693,1.0,0.2,0.8,3.59,1.0,0.8,0.5,4.488,0.5,1.0,0.0,5.386,0.0,1.0,0.0,6.283})))
    .addChild(new ROUTE().setFromNode("Timer1").setFromField("fraction_changed").setToNode("Spinner").setToField("set_fraction"))
    .addChild(new ROUTE().setFromNode("Timer2").setFromField("fraction_changed").setToNode("Tumble").setToField("set_fraction"))
    .addChild(new ROUTE().setFromNode("Spinner").setFromField("value_changed").setToNode("Revolver").setToField("rotation"))
    .addChild(new ROUTE().setFromNode("Tumble").setFromField("value_changed").setToNode("Body2").setToField("rotation"))
    .addChild(new ProtoInstance("HudControlPanel", "HUD").setContainerField("children")
      .addFieldValue(new fieldValue().setName("translation").setValue(new SFVec3f(4.0,-2.0,-10.0)))
      .addFieldValue(new fieldValue().setName("orientation").setValue(new SFRotation(0.0,1.0,0.0,0.0)))
      .addFieldValue(new fieldValue().setName("borderColor").setValue(new SFColor(0.0,0.4,0.0)))
      .addFieldValue(new fieldValue().setName("scale").setValue(new SFVec3f(2.5,1.5,0.05)))
      .addFieldValue(new fieldValue().setName("position").setValue(new SFVec3f(0.0,0.0,0.0)))
      .addFieldValue(new fieldValue().setName("textureMap").setValue(new String[] {"HudControlPanel.gif","http://www.realism.com/vrml/Example/HUD/CP.gif","https://www.web3d.org/x3d/content/examples/Savage/Tools/HeadsUpDisplays/HudControlPanel.gif"})))
    .addChild(new ProximitySensor("Where").setSize(1000.0,1000.0,1000.0))
    .addChild(new Script("Controller").setSourceCode("""
ecmascript:

      function Position (value) {
	msg = 'Control Panel';
	if (value[1] < .5) {
	  if (value[0] > .5) {
	    Light = false;
	    msg = 'Headlight Off';
	   } else {
	    Light = true;
	    msg = 'Headlight On';
	  }
	}
	// Browser.setDescription (msg); // TODO figure this out, see Table 7.2 in Ecmascript SAI
      }

      function Touch (value) {
	Headlight = Light;
      }
""")
      .addField(new field().setName("Headlight").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
      .addField(new field().setName("Position").setType(field.TYPE_SFVEC2F).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("Touch").setType(field.TYPE_SFTIME).setAccessType(field.ACCESSTYPE_INPUTONLY))
      .addField(new field().setName("Light").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setValue(true)))
    .addChild(new ROUTE().setFromNode("HUD").setFromField("hitTexCoord_changed").setToNode("Controller").setToField("Position"))
    .addChild(new ROUTE().setFromNode("HUD").setFromField("touchTime").setToNode("Controller").setToField("Touch"))
    .addChild(new ROUTE().setFromNode("Controller").setFromField("Headlight").setToNode("NavInfo").setToField("headlight")));
            }
            catch (Exception ex)
            {       
                System.err.println ("*** Further hints on X3DJSAIL errors and exceptions at");
                System.err.println ("*** https://www.web3d.org/specifications/java/X3DJSAIL.html");
                throw (ex);
            }
	}
	// end of initialize() method

	/** The initialized model object, created within initialize() method. */
	private X3D x3dModel;

	/** 
	 * Provide a 
	 * <a href="https://dzone.com/articles/java-copy-shallow-vs-deep-in-which-you-will-swim" target="_blank">shallow copy</a>
	 * of the X3D model.
	 * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html">X3D</a>
	 * @return HudControlPanelExample model
	 */
	public X3D getX3dModel()
	{	  
		return x3dModel;
	}
	   
    /** 
     * Default main() method provided for test purposes, uses CommandLine to set global ConfigurationProperties for this object.
     * @param args array of input parameters, provided as arguments
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html#handleArguments-java.lang.String:A-">X3D.handleArguments(args)</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html#validationReport--">X3D.validationReport()</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/CommandLine.html">CommandLine</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/CommandLine.html#USAGE">CommandLine.USAGE</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/ConfigurationProperties.html">ConfigurationProperties</a>
     */
    public static void main(String args[])
    {
        System.out.println("Build this X3D model, showing validation diagnostics...");
        X3D thisExampleX3dModel = new HudControlPanelExample().getX3dModel();
//      System.out.println("X3D model construction complete.");
	
        // next handle command line arguments
        boolean hasArguments = (args != null) && (args.length > 0);
        boolean validate = true; // default
        boolean argumentsLoadNewModel = false;
        String  fileName = new String();

        if (args != null)
        {
                for (String arg : args)
                {
                        if (arg.toLowerCase().startsWith("-v") || arg.toLowerCase().contains("validate"))
                        {
                                validate = true; // making sure
                        }
                        if (arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_X3D) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_CLASSICVRML) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_X3DB) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_VRML97) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_EXI) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_GZIP) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_ZIP) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_HTML) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_XHTML))
                        {
                                argumentsLoadNewModel = true;
                                fileName = arg;
                        }
                }
        }
        if      (argumentsLoadNewModel)
                System.out.println("WARNING: \"Savage.Tools.HeadsUpDisplays.HudControlPanelExample\" model invocation is attempting to load file \"" + fileName + "\" instead of simply validating itself... file loading ignored.");
        else if (hasArguments) // if no arguments provided, this method produces usage warning
                thisExampleX3dModel.handleArguments(args);
	
        if (validate)
        {
            //  System.out.println("--- TODO fix duplicated outputs ---"); // omit when duplicated outputs problem is solved/refactored
		String validationResults = thisExampleX3dModel.validationReport();
            //  System.out.println("-----------------------------------"); // omit when duplicated outputs problem is solved/refactored
                System.out.print("Savage.Tools.HeadsUpDisplays.HudControlPanelExample self-validation test confirmation: ");
                if (!validationResults.equals("success"))
                    System.out.println();
                System.out.println(validationResults.trim());

                // experimental: test X3DJSAIL output files
                // Tools/HeadsUpDisplays/HudControlPanelExample_JavaExport.* file validation is checked when building X3D Example Archives
                String filenameX3D  = "Tools/HeadsUpDisplays/HudControlPanelExample_JavaExport.x3d"; 
                String filenameX3DV = "Tools/HeadsUpDisplays/HudControlPanelExample_JavaExport.x3dv"; 
                String filenameJSON = "Tools/HeadsUpDisplays/HudControlPanelExample_JavaExport.json";
                thisExampleX3dModel.toFileX3D        (filenameX3D);
                thisExampleX3dModel.toFileClassicVRML(filenameX3DV);
// TODO         thisExampleX3dModel.toFileJSON       (filenameJSON);
        }
    }
}
