{ "X3D": {
    "encoding":"UTF-8",
    "@profile":"Immersive",
    "@version":"4.0",
    "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-4.0.xsd",
    "JSON schema":"https://www.web3d.org/specifications/x3d-4.0-JSONSchema.autogenerated.json",
    "head": {
        "meta": [
          {
            "@name":"title",
            "@content":"EventGraphLoopTest.x3d"
          },
          {
            "@name":"description",
            "@content":"Diagnostic scene for tools to test event-graph loop detection"
          },
          {
            "@name":"creator",
            "@content":"Don Brutzman"
          },
          {
            "@name":"created",
            "@content":"4 February 2024"
          },
          {
            "@name":"modified",
            "@content":"4 May 2024"
          },
          {
            "@name":"warning",
            "@content":"includes intentional event loop"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/x3d/stylesheets/X3dToXhtml.xslt"
          },
          {
            "@name":"reference",
            "@content":"EventGraphLoopTestConsoleLog.txt"
          },
          {
            "@name":"reference",
            "@content":"EventGraphLoopTestIndex.html"
          },
          {
            "@name":"specificationSection",
            "@content":"X3D 4.0 Architecture, ISO/IEC 19775-1:2023, 4 Concepts, 4.4.8.4 Loops"
          },
          {
            "@name":"specificationUrl",
            "@content":"https://www.web3d.org/specifications/X3Dv4/ISO-IEC19775-1v4-IS/Part01/concepts.html#Loops"
          },
          {
            "@name":"subject",
            "@content":"X3D event graph loop detection"
          },
          {
            "@name":"identifier",
            "@content":"https://www.web3d.org/x3d/content/examples/X3dForAdvancedModeling/Animation/EventGraphLoopTest.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":"EventGraphLoopTest.x3d"
            }
          },
          { "Background":
            {
              "@skyColor":[1,1,0.858824]
            }
          },
          { "TimeSensor":
            {
              "@DEF":"Clock1",
              "@cycleInterval":8,
              "@loop":true
            }
          },
          { "TimeSensor":
            {
              "@DEF":"Clock2",
              "@cycleInterval":2
            }
          },
          { "TimeSensor":
            {
              "@DEF":"Clock3",
              "@cycleInterval":2
            }
          },
          { "ROUTE":
            {
              "@fromField":"cycleTime",
              "@fromNode":"Clock1",
              "@toField":"startTime",
              "@toNode":"Clock2"
            }
          },
          { "ROUTE":
            {
              "@fromField":"cycleTime",
              "@fromNode":"Clock2",
              "@toField":"startTime",
              "@toNode":"Clock3"
            }
          },
          { "ROUTE":
            {
              "@fromField":"cycleTime",
              "@fromNode":"Clock3",
              "@toField":"startTime",
              "@toNode":"Clock1"
            }
          },
          { "Script":
            {
              "@DEF":"ClockReporter",
              "field": [
                {
                  "@name":"clockStart1",
                  "@accessType":"inputOutput",
                  "@type":"SFTime",
                  "@value":-1
                },
                {
                  "@name":"clockStart2",
                  "@accessType":"inputOutput",
                  "@type":"SFTime",
                  "@value":-1
                },
                {
                  "@name":"clockStart3",
                  "@accessType":"inputOutput",
                  "@type":"SFTime",
                  "@value":-1
                },
                {
                  "@name":"handleClock1",
                  "@accessType":"inputOutput",
                  "@appinfo":"enable indirect contol of node by this Script",
                  "@type":"SFNode",
                  "-children":[
                    { "TimeSensor":
                      {
                        "@USE":"Clock1"
                      }
                    }
                  ]
                },
                {
                  "@name":"loopCounter",
                  "@accessType":"inputOutput",
                  "@appinfo":"loop count",
                  "@type":"SFInt32",
                  "@value":0
                },
                {
                  "@name":"loopCounterString",
                  "@accessType":"outputOnly",
                  "@appinfo":"display latest loop count",
                  "@type":"MFString"
                }
              ],
              "#sourceCode":[
"",
"",
"ecmascript:",
"",
"",
"function initialize()",
"{",
"    Browser.println ('[Script ClockReporter] initialize()');",
"}",
"",
"function clockStart1 (eventValue)",
"{",
"    // input eventValue received for inputOutput field",
"    clockStart1 = eventValue;",
"    Browser.println ('[Script ClockReporter] clockStart1(' + eventValue + ')');",
"}",
"",
"function clockStart2 (eventValue)",
"{",
"    // input eventValue received for inputOutput field",
"    clockStart2 = eventValue;",
"    Browser.println ('[Script ClockReporter] clockStart2(' + eventValue + ')');",
"}",
"",
"function clockStart3 (eventValue)",
"{",
"    // input eventValue received for inputOutput field",
"    clockStart3 = eventValue;",
"    loopCounter++;",
"    // send single-line MFString output event to Text node's string field",
"    loopCounterString = new MFString('loop ' + loopCounter);",
"    Browser.println ('[Script ClockReporter] clockStart3(' + eventValue + ') received event to start text spinning');",
"}",
"",
""
]
            }
          },
          { "ROUTE":
            {
              "@fromField":"cycleTime",
              "@fromNode":"Clock3",
              "@toField":"clockStart3",
              "@toNode":"ClockReporter"
            }
          },
          {
            "#comment":"debug <ROUTE fromField='cycleTime' fromNode='Clock1' toField='clockStart1' toNode='ClockReporter'/> <ROUTE fromField='cycleTime' fromNode='Clock2' toField='clockStart2' toNode='ClockReporter'/>"
          },
          { "Transform":
            {
              "@DEF":"RotatingTransform",
              "@translation":[0,1,0],
              "-children":[
                { "Shape":
                  {
                    "@DEF":"SpinnableTextShape",
                    "-geometry":
                      { "Text":
                        {
                          "@string":["EventGraphLoopTest","includes a","three-ROUTE event loop"],
                          "-fontStyle":
                            { "FontStyle":
                              {
                                "@DEF":"BoldFontStyle",
                                "@family":["SANS"],
                                "@justify":["MIDDLE","MIDDLE"],
                                "@size":0.8,
                                "@style":"BOLD"
                              }
                            }
                        }
                      },
                    "-appearance":
                      { "Appearance":
                        {
                          "@DEF":"TextAppearance",
                          "-material":
                            { "Material":
                              {
                                "@diffuseColor":[1,0.4,0.2]
                              }
                            }
                        }
                      }
                  }
                }
              ]
            }
          },
          { "Transform":
            {
              "@DEF":"LoopCounterTransform",
              "@scale":[0.8,0.8,0.8],
              "@translation":[0,-1.5,0],
              "-children":[
                { "Shape":
                  {
                    "@DEF":"LoopCounterTextShape",
                    "-geometry":
                      { "Text":
                        {
                          "@DEF":"LoopCounterText",
                          "@string":["loop 0"],
                          "-fontStyle":
                            { "FontStyle":
                              {
                                "@USE":"BoldFontStyle"
                              }
                            }
                        }
                      },
                    "-appearance":
                      { "Appearance":
                        {
                          "@USE":"TextAppearance"
                        }
                      }
                  }
                }
              ]
            }
          },
          { "ROUTE":
            {
              "@fromField":"loopCounterString",
              "@fromNode":"ClockReporter",
              "@toField":"string",
              "@toNode":"LoopCounterText"
            }
          },
          { "OrientationInterpolator":
            {
              "@DEF":"Spinner",
              "@key":[0,0.3333,0.6667,1],
              "@keyValue":[0,1,0,0,0,1,0,2.094395,0,1,0,4.18879,0,1,0,0]
            }
          },
          { "ROUTE":
            {
              "@fromField":"fraction_changed",
              "@fromNode":"Clock3",
              "@toField":"set_fraction",
              "@toNode":"Spinner"
            }
          },
          { "ROUTE":
            {
              "@fromField":"value_changed",
              "@fromNode":"Spinner",
              "@toField":"rotation",
              "@toNode":"RotatingTransform"
            }
          }
        ]
    }
  }
}