####################################################################################################
#
# Invoking X3D model self-test:
#
#   $ python Example05.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='Example05.x3d',name='title'),
    meta(content='Don Brutzman',name='creator'),
    meta(content='24 May 2000',name='created'),
    meta(content='28 October 2019',name='modified'),
    meta(content='X3D working group',name='creator'),
    meta(content="VRML 97 specification example: This Script node decides whether or not to open a bank vault given openVault and combinationEntered messages. To do this, it remembers whether or not the correct combination has been entered. The Script node combined with a Sphere, a TouchSensor and a Sound node to show how is works. When the pointing device is over the sphere, the combinationEntered eventIn of the Script is sent. Then, when the Sphere is touched (typically when the mouse button is pressed) the Script is sent the openVault eventIn. This generates the vaultUnlocked eventOut which starts a 'click' sound.",name='description'),
    meta(content='originals/exampleD_5.wrl',name='specificationUrl'),
    meta(content='VRML 97, ISO/IEC 14772-1, Part 1: Functional specification and UTF-8 encoding, D.5 Scripting example',name='specificationSection'),
    meta(content='https://www.web3d.org/documents/specifications/14772/V2.0/part1/examples.html#D.5',name='specificationUrl'),
    meta(content='https://www.web3d.org/x3d/content/examples/Basic/Vrml97Specification/Example05.x3d',name='identifier'),
    meta(content='X3D-Edit 3.3, https://www.web3d.org/x3d/tools/X3D-Edit',name='generator'),
    meta(content='../license.html',name='license')]),
  Scene=Scene(
    children=[
    Comment('Warning: VRML97-style scripting, not X3D Scene Authoring Interface (SAI)'),
    WorldInfo(title='Example05.x3d'),
    Script(DEF='OpenVault',
      field=[
      Comment('field tags are declarations of what interfaces are in this Script node'),
      field(accessType='inputOnly',name='openVault',type='SFTime'),
      field(accessType='inputOnly',name='combinationEntered',type='SFBool'),
      field(accessType='outputOnly',name='vaultUnlocked',type='SFTime'),
      field(accessType='initializeOnly',name='unlocked',type='SFBool',value=False)],

    sourceCode="""
ecmascript:
function combinationEntered (value)
{
	unlocked = value;
}
function openVault(value)
{
	if (unlocked) vaultUnlocked = value;
}
"""),
    Shape(
      appearance=Appearance(
        material=Material(diffuseColor=(1,0,0))),
      geometry=Sphere(),),
    Sound(maxBack=1000,maxFront=1000,minBack=1000,minFront=1000,
      source=AudioClip(DEF='Click',description='click',stopTime=1,url=["click.wav","https://www.web3d.org/x3d/content/examples/Basic/Vrml97Specification/click.wav"])),
    TouchSensor(DEF='TS',description='touch ball to hear a click'),
    ROUTE(fromField='isOver',fromNode='TS',toField='combinationEntered',toNode='OpenVault'),
    ROUTE(fromField='touchTime',fromNode='TS',toField='openVault',toNode='OpenVault'),
    ROUTE(fromField='vaultUnlocked',fromNode='OpenVault',toField='startTime',toNode='Click')])
)

### X3D model conversion complete ###

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

print('Self-test diagnostics for Example05.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 Example05.py load and self-test diagnostics complete.")
