{ "X3D": {
    "encoding":"UTF-8",
    "@profile":"Immersive",
    "@version":"3.0",
    "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.0.xsd",
    "JSON schema":"https://www.web3d.org/specifications/x3d-4.0-JSONSchema.autogenerated.json",
    "head": {
        "meta": [
          {
            "@name":"title",
            "@content":"ViewpointSequencerPrototype.x3d"
          },
          {
            "@name":"description",
            "@content":"Animate through a set of Viewpoint or GeoViewpoint nodes and repeat"
          },
          {
            "@name":"creator",
            "@content":"Don Brutzman"
          },
          {
            "@name":"created",
            "@content":"10 December 2002"
          },
          {
            "@name":"modified",
            "@content":"3 February 2024"
          },
          {
            "@name":"subject",
            "@content":"Viewpoint Tour"
          },
          {
            "@name":"reference",
            "@content":"CubeWithLabeledSidesViewpointSequencerIndex.html"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/x3d/content/examples//Basic/Geospatial/CaliforniaCampusesIndex.html"
          },
          {
            "@name":"info",
            "@content":"Two versions of this scene are maintained in order to avoid Cross-Origin Resource Sharing (CORS) restrictions when referenced from X3D models embedded inside HTML."
          },
          {
            "@name":"reference",
            "@content":"https://savage.nps.edu/Savage/Tools/Animation/ViewpointSequencerPrototype.x3d"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#ScalarInterpolator"
          },
          {
            "@name":"identifier",
            "@content":"https://www.web3d.org/x3d/content/examples/X3dForAdvancedModeling/Animation/ViewpointSequencerPrototype.x3d"
          },
          {
            "@name":"generator",
            "@content":"X3D-Edit 4.0, https://www.web3d.org/x3d/tools/X3D-Edit"
          },
          {
            "@name":"license",
            "@content":"../../license.html"
          },
          {
            "@name":"translated",
            "@content":"16 April 2026"
          },
          {
            "@name":"generator",
            "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html"
          },
          {
            "@name":"reference",
            "@content":"X3D JSON encoding: https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding"
          }
        ]
    },
    "Scene": {
        "-children":[
          { "WorldInfo":
            {
              "@title":"ViewpointSequencerPrototype.x3d"
            }
          },
          { "ProtoDeclare":
            {
              "@name":"ViewpointSequencer",
              "@appinfo":"Sequentially binds each Viewpoint in a set of Viewpoint USE nodes, creating an automatic tour for a scene",
              "ProtoInterface": {
                  "field": [
                    {
                      "@name":"viewpoints",
                      "@accessType":"initializeOnly",
                      "@appinfo":"Viewpoint USE nodes that are sequentially bound",
                      "@type":"MFNode",
                      "-children":[
                        {
                          "#comment":"initialization nodes (if any) go here"
                        }
                      ]
                    },
                    {
                      "@name":"interval",
                      "@accessType":"inputOutput",
                      "@appinfo":"number of seconds between viewpoint shifts",
                      "@type":"SFTime",
                      "@value":5
                    },
                    {
                      "@name":"enabled",
                      "@accessType":"inputOutput",
                      "@appinfo":"whether ViewpointSequencer is enabled or not",
                      "@type":"SFBool",
                      "@value":true
                    },
                    {
                      "@name":"set_enabled",
                      "@accessType":"inputOnly",
                      "@appinfo":"whether ViewpointSequencer is enabled or not",
                      "@type":"SFBool"
                    },
                    {
                      "@name":"previous",
                      "@accessType":"inputOnly",
                      "@appinfo":"bind previous Viewpoint in list",
                      "@type":"SFBool"
                    },
                    {
                      "@name":"next",
                      "@accessType":"inputOnly",
                      "@appinfo":"bind next Viewpoint in list",
                      "@type":"SFBool"
                    },
                    {
                      "@name":"toggleMessage",
                      "@accessType":"inputOutput",
                      "@appinfo":"Select message to toggle ViewpointSequencer",
                      "@type":"MFString",
                      "@value":["Click text to toggle","ViewpointSequencer"]
                    },
                    {
                      "@name":"toggleMessageFontSize",
                      "@accessType":"initializeOnly",
                      "@appinfo":"Font size for toggleMessage text",
                      "@type":"SFFloat",
                      "@value":1
                    },
                    {
                      "@name":"toggleMessageColor",
                      "@accessType":"inputOutput",
                      "@appinfo":"Color for toggleMessage text",
                      "@type":"SFColor",
                      "@value":[0.6,0.4,0.13]
                    },
                    {
                      "@name":"traceEnabled",
                      "@accessType":"inputOutput",
                      "@appinfo":"enable console output",
                      "@type":"SFBool",
                      "@value":false
                    }
                  ]
              },
              "ProtoBody": {
                  "-children":[
                    { "Group":
                      {
                        "@DEF":"ProtoBodyGroup",
                        "-children":[
                          { "TimeSensor":
                            {
                              "@DEF":"Trigger",
                              "@loop":true,
                              "IS": {
                                  "connect": [
                                    {
                                      "@nodeField":"enabled",
                                      "@protoField":"enabled"
                                    },
                                    {
                                      "@nodeField":"cycleInterval",
                                      "@protoField":"interval"
                                    }
                                  ]
                              }
                            }
                          },
                          { "TimeSensor":
                            {
                              "@DEF":"TraceHolder",
                              "IS": {
                                  "-children":[
                                    {
                                      "#comment":"this node and field is used to hold value of ProtoInterface field"
                                    }
                                  ],
                                  "connect": [
                                    {
                                      "@nodeField":"enabled",
                                      "@protoField":"traceEnabled"
                                    }
                                  ]
                              }
                            }
                          },
                          { "Script":
                            {
                              "@DEF":"SequencerScript",
                              "@directOutput":true,
                              "field": [
                                {
                                  "@name":"viewpoints",
                                  "@accessType":"initializeOnly",
                                  "@type":"MFNode"
                                },
                                {
                                  "@name":"set_enabled",
                                  "@accessType":"inputOnly",
                                  "@appinfo":"whether ViewpointSequencer is enabled or not",
                                  "@type":"SFBool"
                                },
                                {
                                  "@name":"TriggerNode",
                                  "@accessType":"initializeOnly",
                                  "@type":"SFNode",
                                  "-children":[
                                    { "TimeSensor":
                                      {
                                        "@USE":"Trigger"
                                      }
                                    }
                                  ]
                                },
                                {
                                  "@name":"TraceHolderNode",
                                  "@accessType":"initializeOnly",
                                  "@type":"SFNode",
                                  "-children":[
                                    { "TimeSensor":
                                      {
                                        "@USE":"TraceHolder"
                                      }
                                    }
                                  ]
                                },
                                {
                                  "@name":"triggerNext",
                                  "@accessType":"inputOnly",
                                  "@type":"SFTime"
                                },
                                {
                                  "@name":"previous",
                                  "@accessType":"inputOnly",
                                  "@type":"SFBool"
                                },
                                {
                                  "@name":"next",
                                  "@accessType":"inputOnly",
                                  "@type":"SFBool"
                                },
                                {
                                  "@name":"index",
                                  "@accessType":"initializeOnly",
                                  "@type":"SFInt32",
                                  "@value":0
                                },
                                {
                                  "@name":"viewpointCount",
                                  "@accessType":"initializeOnly",
                                  "@type":"SFInt32",
                                  "@value":0
                                },
                                {
                                  "@name":"traceEnabled",
                                  "@accessType":"initializeOnly",
                                  "@type":"SFBool",
                                  "@value":false
                                }
                              ],
                              "-children":[
                                {
                                  "#comment":"local Script variables needing persistent values"
                                }
                              ],
                              "IS": {
                                  "connect": [
                                    {
                                      "@nodeField":"viewpoints",
                                      "@protoField":"viewpoints"
                                    },
                                    {
                                      "@nodeField":"previous",
                                      "@protoField":"previous"
                                    },
                                    {
                                      "@nodeField":"next",
                                      "@protoField":"next"
                                    },
                                    {
                                      "@nodeField":"set_enabled",
                                      "@protoField":"set_enabled"
                                    }
                                  ]
                              },
                              "#sourceCode":[
"",
"",
"ecmascript:",
"",
"function initialize ()",
"{",
"\tindex = 0;",
"\tviewpointCount = viewpoints.length;",
"\ttraceEnabled = TraceHolderNode.loop;",
"",
"\ttracePrint ('initialize: viewpoints.length=' + viewpointCount);",
"\ttracePrint ('initialize: Viewpoint [' + index + '] ' + viewpoints[index].description);",
"",
"\tif (TriggerNode.enabled=='false') return;",
"\tif (viewpointCount > 0) viewpoints[index].set_bind = true;",
"}",
"",
"function set_enabled (newValue, timeStamp)",
"{",
"\tenabled = newValue;",
"\ttracePrint ('enabled=' + newValue);",
"        if ((newValue == true) && (viewpoints.length >= 1))",
"            viewpoints[0].bind = true;",
"}",
"",
"function triggerNext(triggerTime, timeStamp)",
"{",
"\tif ((TriggerNode.enabled=='false') || (viewpointCount==0)) return;",
"\tif (index < viewpointCount - 1)",
"\t\tindex++;",
"\telse\tindex = 0;",
"\tif (viewpointCount > 1) viewpoints[index].set_bind = true;",
"\ttracePrint ('triggerNext: Viewpoint [' + index + '] ' + viewpoints[index].description);",
"}",
"",
"function previous (value, timeStamp)",
"{",
"  if ((TriggerNode.enabled=='false') || (viewpointCount==0)) return;",
"  if (value==true) // trigger on true events only",
"  {",
"\tif (index > 0)",
"\t\tindex--;",
"\telse\tindex = viewpointCount - 1;",
"\tif (viewpointCount > 1) viewpoints[index].set_bind = true;",
"\ttracePrint ('previous: Viewpoint [' + index + '] ' + viewpoints[index].description);",
"  }",
"}",
"function next (value, timeStamp)",
"{",
"  if ((TriggerNode.enabled=='false') || (viewpointCount==0)) return;",
"  if (value==true) // trigger on true events only",
"  {",
"\tif (index < viewpointCount - 1)",
"\t\tindex++;",
"\telse\tindex = 0;",
"\tif (viewpointCount > 1) viewpoints[index].set_bind = true;",
"\ttracePrint ('next: Viewpoint [' + index + '] ' + viewpoints[index].description);",
"  }",
"}",
"",
"function tracePrint(outputString)",
"{",
"\tif (traceEnabled) Browser.println ('[ViewpointSequencer] ' + outputString);",
"}",
"",
"function alwaysPrint(outputString)",
"{",
"\tBrowser.println ('[ViewpointSequencer] ' + outputString);",
"}",
"",
""
]
                            }
                          },
                          { "ROUTE":
                            {
                              "@fromField":"cycleTime",
                              "@fromNode":"Trigger",
                              "@toField":"triggerNext",
                              "@toNode":"SequencerScript"
                            }
                          },
                          { "Group":
                            {
                              "@DEF":"TouchTextGroup",
                              "-children":[
                                { "TouchSensor":
                                  {
                                    "@DEF":"TouchTextSensor",
                                    "@description":"Click text to toggle ViewpointSequencer"
                                  }
                                },
                                { "Billboard":
                                  {
                                    "@axisOfRotation":[0,0,0],
                                    "-children":[
                                      { "Shape":
                                        {
                                          "-geometry":
                                            { "Text":
                                              {
                                                "IS": {
                                                    "connect": [
                                                      {
                                                        "@nodeField":"string",
                                                        "@protoField":"toggleMessage"
                                                      }
                                                    ]
                                                },
                                                "-fontStyle":
                                                  { "FontStyle":
                                                    {
                                                      "@justify":["MIDDLE","MIDDLE"],
                                                      "IS": {
                                                          "connect": [
                                                            {
                                                              "@nodeField":"size",
                                                              "@protoField":"toggleMessageFontSize"
                                                            }
                                                          ]
                                                      }
                                                    }
                                                  }
                                              }
                                            },
                                          "-appearance":
                                            { "Appearance":
                                              {
                                                "-material":
                                                  { "Material":
                                                    {
                                                      "IS": {
                                                          "connect": [
                                                            {
                                                              "@nodeField":"diffuseColor",
                                                              "@protoField":"toggleMessageColor"
                                                            }
                                                          ]
                                                      }
                                                    }
                                                  }
                                              }
                                            }
                                        }
                                      },
                                      {
                                        "#comment":"An invisible box behind the string helps to toggle the ViewpointSequencer"
                                      },
                                      { "Shape":
                                        {
                                          "-geometry":
                                            { "Box":
                                              {
                                                "@size":[7.8,2,0.1]
                                              }
                                            },
                                          "-appearance":
                                            { "Appearance":
                                              {
                                                "-material":
                                                  { "Material":
                                                    {
                                                      "@diffuseColor":[1,1,1],
                                                      "@transparency":1
                                                    }
                                                  }
                                              }
                                            }
                                        }
                                      }
                                    ]
                                  }
                                },
                                { "BooleanToggle":
                                  {
                                    "@DEF":"TouchToggle"
                                  }
                                },
                                { "ROUTE":
                                  {
                                    "@fromField":"isActive",
                                    "@fromNode":"TouchTextSensor",
                                    "@toField":"set_boolean",
                                    "@toNode":"TouchToggle"
                                  }
                                },
                                {
                                  "#comment":"TouchToggle toggle_changed should likely revert to TouchToggle toggle when inputOutput fields supported in Script, or native implementation provided."
                                },
                                { "ROUTE":
                                  {
                                    "@fromField":"toggle",
                                    "@fromNode":"TouchToggle",
                                    "@toField":"set_enabled",
                                    "@toNode":"SequencerScript"
                                  }
                                },
                                { "ROUTE":
                                  {
                                    "@fromField":"toggle",
                                    "@fromNode":"TouchToggle",
                                    "@toField":"enabled",
                                    "@toNode":"Trigger"
                                  }
                                }
                              ]
                            }
                          }
                        ]
                      }
                    }
                  ]
              }
            }
          },
          {
            "#comment":"===============Example=============="
          },
          { "Anchor":
            {
              "@description":"select to view ViewpointSequencer example",
              "@parameter":["target=_blank"],
              "@url":["ViewpointSequencerExample.x3d","https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/ViewpointSequencerExample.x3d","ViewpointSequencerExample.wrl","https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/ViewpointSequencerExample.wrl"],
              "-children":[
                { "Shape":
                  {
                    "-geometry":
                      { "Text":
                        {
                          "@string":["ViewpointSequencerPrototype","defines a prototype","Click text to see example scene","ViewpointTourExample"],
                          "-fontStyle":
                            { "FontStyle":
                              {
                                "@justify":["MIDDLE","MIDDLE"],
                                "@size":0.9
                              }
                            }
                        }
                      },
                    "-appearance":
                      { "Appearance":
                        {
                          "-material":
                            { "Material":
                              {
                                "@diffuseColor":[1,1,0.2]
                              }
                            }
                        }
                      }
                  }
                },
                { "Shape":
                  {
                    "-children":[
                      {
                        "#comment":"transparent Box to make text more selectable"
                      }
                    ],
                    "-geometry":
                      { "Box":
                        {
                          "@size":[11,5,0.1]
                        }
                      },
                    "-appearance":
                      { "Appearance":
                        {
                          "-material":
                            { "Material":
                              {
                                "@diffuseColor":[1,1,1],
                                "@transparency":1
                              }
                            }
                        }
                      }
                  }
                }
              ]
            }
          }
        ]
    }
  }
}