####################################################################################################
#
# Invoking X3D model self-test:
#
#   $ python MfdScreen.py
#
# Python package x3d.py package is available on PyPI for import.
#   This approach simplifies Python X3D deployment and use.
#   https://pypi.org/project/x3d
#
# Installation:
#       pip install x3d
# or
#       python -m pip install x3d
#
# Developer options for loading x3d package in other Python programs:
#
#    from x3d import *  # preferred approach, terser source that avoids x3d.* class prefixes
#
# or
#    import x3d         # traditional way to subclass x3d package, all classes require x3d.* prefix,
#                       # but python source is very verbose, for example x3d.Material x3d.Shape etc.
#                       # X3dToPython.xslt stylesheet insertPackagePrefix=true supports this option.
#
# Project home page:    # X3D Python Scene Access Interface Library (X3DPSAIL)
#                       # https://www.web3d.org/x3d/stylesheets/python/python.html
# Conversion generator: # https://www.web3d.org/x3d/stylesheets/X3dToPython.xslt
#
####################################################################################################

from x3d import *

newModel=X3D(profile='Immersive',version='3.0',
  head=head(
    children=[
    meta(content='MfdScreen.x3d',name='title'),
    meta(content='MultiFunctionDisplay (MFD) screen that is inlined to create the cockpit console of a helicopter',name='description'),
    meta(content='Doug Miller (original creator), Jane Wu (adapted from the original mfd.wrl created for vrtp demo helicopter)',name='creator'),
    meta(content='19 February 1999',name='created'),
    meta(content='20 October 2019',name='modified'),
    meta(content='Del Beilstein',name='contributor'),
    meta(content='https://www.web3d.org/x3d/content/examples/Savage/AircraftHelicopters/OH58dKiowaWarriorUnitedStates/MfdScreen.x3d',name='identifier'),
    meta(content='T62.jpg',name='reference'),
    meta(content='M1Abrams.jpg',name='reference'),
    meta(content='MfdScreen.jpg',name='reference'),
    meta(content='50cal.wav',name='reference'),
    meta(content='X3D-Edit 3.2, https://www.web3d.org/x3d/tools/X3D-Edit',name='generator'),
    meta(content='../../license.html',name='license')]),
  Scene=Scene(
    children=[
    WorldInfo(title='MfdScreen.x3d'),
    Viewpoint(description='Close-up view of Multi-FunctionDisplay',position=(0,0,0.3)),
    Group(
      children=[
      Shape(
        appearance=Appearance(DEF='GRAY',
          material=Material(diffuseColor=(0.2,0.2,0.2))),
        geometry=Box(size=(0.26,0.21,0.05))),
      Transform(translation=(0.00,0.00,0.03),
        children=[
        Switch(DEF='MFD_SCREEN',whichChoice=3,
          children=[
          Shape(
            appearance=Appearance(
              material=Material(DEF='GREEN_COLOR',diffuseColor=(0.0,1.0,0.0))),
            geometry=IndexedFaceSet(DEF='MFD_GEOMETRY',coordIndex=[0,1,2,3,-1],
              coord=Coordinate(point=[(-0.09,-0.07,0.01),(0.09,-0.07,0.01),(0.09,0.07,0.01),(-0.09,0.07,0.01)]))),
          Shape(
            appearance=Appearance(
              material=Material(USE='GREEN_COLOR'),
              texture=ImageTexture(url=["T62.jpg","https://www.web3d.org/x3d/content/examples/Savage/AircraftHelicopters/OH58dKiowaWarriorUnitedStates/T62.jpg"])),
            geometry=IndexedFaceSet(USE='MFD_GEOMETRY')),
          Shape(
            appearance=Appearance(
              material=Material(USE='GREEN_COLOR'),
              texture=ImageTexture(url=["M1Abrams.jpg","https://www.web3d.org/x3d/content/examples/Savage/AircraftHelicopters/OH58dKiowaWarriorUnitedStates/M1Abrams.jpg"])),
            geometry=IndexedFaceSet(USE='MFD_GEOMETRY')),
          Shape(
            appearance=Appearance(
              material=Material(USE='GREEN_COLOR'),
              texture=ImageTexture(url=["MfdScreen.jpg","https://www.web3d.org/x3d/content/examples/Savage/AircraftHelicopters/OH58dKiowaWarriorUnitedStates/MfdScreen.jpg"])),
            geometry=IndexedFaceSet(USE='MFD_GEOMETRY'))])]),
      Switch(DEF='FIFTY_CAL_SOUND',whichChoice=0,
        children=[
        Sound(
          source=AudioClip(description='50 caliber gun',loop=True,url=["50cal.wav","https://www.web3d.org/x3d/content/examples/Savage/AircraftHelicopters/OH58dKiowaWarriorUnitedStates/50cal.wav"]))]),
      Transform(translation=(-0.11,-0.05,0.025),
        children=[
        Shape(DEF='BUTTON',
          appearance=Appearance(DEF='OFF_WHITE',
            material=Material(diffuseColor=(0.75,0.75,0.75))),
          geometry=Box(size=(0.02,0.02,0.01)))]),
      Transform(translation=(-0.11,-0.015,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(-0.11,0.02,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(-0.11,0.055,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(0.11,-0.05,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(0.11,-0.015,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(0.11,0.02,0.025),
        children=[
        Shape(USE='BUTTON'),
        TouchSensor(DEF='RIGHT_BUTTON2',description='touch to activate')]),
      Transform(translation=(0.11,0.055,0.025),
        children=[
        Shape(USE='BUTTON'),
        TouchSensor(DEF='RIGHT_BUTTON1',description='touch to activate')]),
      Transform(translation=(-0.065,-0.09,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(-0.035,-0.09,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(0.035,-0.09,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(translation=(0.065,-0.09,0.025),
        children=[
        Shape(USE='BUTTON')]),
      Transform(rotation=(1.0,0.0,0.0,1.57),translation=(-0.11,-0.085,0.025),
        children=[
        Shape(DEF='KNOB',
          appearance=Appearance(
            material=Material(USE='GREEN_COLOR')),
          geometry=Cylinder(height=0.02,radius=0.0125))]),
      Transform(rotation=(1.0,0.0,0.0,1.57),translation=(0.11,-0.085,0.025),
        children=[
        Shape(USE='KNOB')])]),
    Script(DEF='CycleSelector',
      field=[
      field(accessType='initializeOnly',name='value',type='SFInt32',value=0),
      field(accessType='inputOnly',name='set_boolean',type='SFBool'),
      field(accessType='outputOnly',name='value_changed',type='SFInt32')],

    sourceCode="""
ecmascript:
function set_boolean(bool, eventTime) {
 if (bool == false)
  return;
 if (value == 3)
  value = -1;
 value++;
 value_changed = value;
}
"""),
    Script(DEF='FiftyCalOnOffToggle',
      field=[
      field(accessType='initializeOnly',name='value',type='SFBool',value=False),
      field(accessType='inputOnly',name='set_boolean',type='SFBool'),
      field(accessType='outputOnly',name='value_changed',type='SFInt32')],

    sourceCode="""
ecmascript:
function set_boolean(bool, eventTime) {
   if (bool == false)
      return;

   value_changed = value;

   if (value == true)
      value = false;
   else
      value = true;
}
"""),
    Comment('Cycle selectors routes'),
    ROUTE(fromField='isActive',fromNode='RIGHT_BUTTON1',toField='set_boolean',toNode='CycleSelector'),
    ROUTE(fromField='value_changed',fromNode='CycleSelector',toField='set_whichChoice',toNode='MFD_SCREEN'),
    Comment('50Cal Routes'),
    ROUTE(fromField='isActive',fromNode='RIGHT_BUTTON2',toField='set_boolean',toNode='FiftyCalOnOffToggle'),
    ROUTE(fromField='value_changed',fromNode='FiftyCalOnOffToggle',toField='set_whichChoice',toNode='FIFTY_CAL_SOUND')])
)

### X3D model conversion complete ###

####################################################################################################
# Self-test diagnostics
####################################################################################################

print('Self-test diagnostics for MfdScreen.py:')
if        metaDiagnostics(newModel): # built-in utility method in X3D class
    print(metaDiagnostics(newModel)) # display meta info, hint, warning, error, TODO values in this model
# print('check newModel.XML() serialization...')
newModelXML= newModel.XML() # test export method XML() for exceptions during export
newModel.XMLvalidate()
# print(newModelXML) # diagnostic

try:
#   print('check newModel.VRML() serialization...')
    newModelVRML=newModel.VRML() # test export method VRML() for exceptions during export
    # print(prependLineNumbers(newModelVRML)) # debug
    print("Python-to-VRML export of VRML output successful", flush=True)
except Exception as err: # usually BaseException
    # https://stackoverflow.com/questions/18176602/how-to-get-the-name-of-an-exception-that-was-caught-in-python
    print("*** Python-to-VRML export of VRML output failed:", type(err).__name__, err)
    if newModelVRML: # may have failed to generate
        print(prependLineNumbers(newModelVRML, err.lineno))

try:
#   print('check newModel.JSON() serialization...')
    newModelJSON=newModel.JSON() # test export method JSON() for exceptions during export
#   print(prependLineNumbers(newModelJSON)) # debug
    print("Python-to-JSON export of JSON output successful (under development)")
except Exception as err: # usually SyntaxError
    print("*** Python-to-JSON export of JSON output failed:", type(err).__name__, err)
    if newModelJSON: # may have failed to generate
        print(prependLineNumbers(newModelJSON,err.lineno))

print("python MfdScreen.py load and self-test diagnostics complete.")
