Extensible 3D (X3D)
Part 1: Architecture and base components
29 Scripting component
脚本组件
这部分组件的名称是 "Scripting""。当在 COMPONENT 语句中引用这个组件时需要使用这个名称(参见 7.2.3.4 Component 语句)。
本条款描述了 ISO/IEC 19775 标准这部分中的 Scripting component (脚本组件)。其中包括如何使用 Script 节点来改变 X3D 场景。表 29.1 列出了这一条款的主要主题。
作者若常常需要 X3D 境界根据用户输入、外部事件、当前境界的状态做相应的动态修改。“如果保险库当前是关闭的且输入了正确的密码,则打开保险库” 这样的命题形象地说明需要解决的问题类型。这种判断是通过内部的 Script 节点(见 Script)或外部的其它应用程序来使用 SAI(Scene Access Interface - 场景存取界面)程序化的表示的。这些应用程序称为 脚本环境(scripting environments)。在两种情况下,脚本环境都可以接受事件,处理事件,并发送新的事件。脚本环境可以为后续的执行保留信息追踪(例如随时间流逝而保持内部的状态)。
本子条款描述了所有脚本存取的一般机制和语义。2.[I19775-2] 定义了一系列的抽象脚本服务并指定了绑定到这些服务的语言。对于内部脚本,事件处理由 Script 节点的 url 域包含(或引用)的程序或脚本执行。这个程序或脚本可以由任何的浏览器支持的语言写出。
当脚本节点接受到一个事件时将被激活。浏览器将执行 Script 节点 url 域中的程序(如果需要将会把程序传输到一个外部解释器中)。这个程序可以执行不同的动作,包括发送出事件(用来改变场景),执行计算,和其它 Internet 上的服务器进行通信。事件处理顺序的详细描述见 4. 概念 Concepts 。
按照 29.2.3, initialize() and shutdown() 中的规定,Script 节点可以在初始化或关闭的时候执行。某些脚本语言可能允许创建和脚本分离的处理进程,这将导致连续执行(见 29.2.5, 异步脚本)。
Script 节点按时间戳的顺序接受事件。任何处理一个事件生成的结果事件,都被赋予一个导致结果事件生成的事件相同的时间戳。虽然 Script 的实际执行将花费一定的时间,但是从概念上看 Script 节点接受并处理一个事件是不花费时间的。
当 Script 节点接受到一个 set_url 事件,且事件中包含的脚本和先前初始化的脚本 URL 不同时,当前脚本的 shutdown() 服务将被调用(见 29.2.3, initialize() 和 shutdown())。直到新的脚本可用之前,脚本表现为无可执内容。当新脚本可用时,将调用 Initialize() 服务。极限的情况是 URL 包含了一旦收到 set_url 事件就可以立即执行的嵌入代码(例如:ecmascript: 协议)。在这种情况下,可以假定动态路由请求完成后,旧的代码被卸载,新的代码立即被载入。
绑定的脚本语言可以定义一个 initialize() 方法。在浏览器向用户呈现场景前,以及包含此 Script 节点的 X3D 文件中任何节点发出的事件被处理之前,应调用这个方法。由 initialize() 方法生成的事件的时间戳应小于此 Script 节点生成的其它事件的时间戳。这允许脚本在用户和场景交互之前执行初始化任务。
同样的,绑定的脚本语言可以定义一个 shutdown() 方法。当相应的 Script 节点被删除时,或包含此 Script 节点的场景被卸载或被另一个场景替换的时候,应调用这个方法。这个方法可以用来进行清理操作,如通知外部机制移除临时文件。当 shutdown() 方法完成以后,此脚本的其它方法将不能再被调用,然而在关闭的过程中,shutdown() 方法可以调用方法或发送事件。由 shutdown() 方法生成的事件,如果被路由到将被删除的节点且此动作将再次导致 shutdown() 方法执行,则此事件将不会被发送。在 shutdown() 方法执行完成以后,才会删除包含此 shutdown() 方法的 Script 节点。
绑定的脚本语言可以定义一个 eventsProcessed() 方法,此方法在接受到一个或多个事件后调用。此方法允许脚本不依赖接受事件的顺序,与等价的一接受到事件就生成事件的脚本相比,此方法生成较少的事件。如果eventsProcessed() 在其它的时间相关的方式中使用,因为不同的浏览器执行可能在不同时间调用eventsProcessed() ,则 eventsProcessed() 可能是不确定的。
对于单个的事件级联,给定的 Script 节点的 eventsProcessed 方法应至多调用一次。由 eventsProcessed() 方法生成的事件将被给定一个最后事件处理的时间戳。
绑定的脚本语言可以定义一个 prepareEvents() 方法,此方法在每个时间戳只调用一次。prepareEvents() 在任何 ROUTE 处理前调用,这允许 Script 收集诸如从网络序列的输入或域监听调用这样的异步生成的数据,生成的事件将按照浏览器一般事件处理序列的方式,并象处理内建的传感器节点那样处理。
存取(经由 SFNode 域和 MFNode 域)了其它节点且其 directOutput 域被设置为 TRUE
的脚本可以直接向这些节点发送事件,也能读取这些节点域的最新值。
当设置其它节点中的值时,执行应通过向其它节点的相应的域发送输入事件以设定其值。这些事件应为当前事件级联的一部分(参见 4.4.8.3, 执行模型 Execution model)。
某些 X3D 浏览器支持的脚本允许 Script 节点自己生成事件,以允许用户创建新的功能类似传感器节点的 Script 节点。这种情况下,脚本生成将导致事件级联的初始事件,这个初始事件的适当的时间戳将由脚本语言和/或浏览器决定。这样的事件将被排序入事件流中,并按处理其它事件的包括回路在内的相同的规则处理。
Script 节点的 url 域应允许包括内嵌的脚本和经由 URL 引用的脚本。返回的数据的 MIME 类型 将定义语言的类型。另外,对于特定的语言,可以按照 9.2.3, Scripting language protocols 中脚本语言协议(依次推断语言类型)的定义把指令内嵌地包含在 Script 节点中。
例如,以下的 Script 节点有一个名为 start 的域和一个指定了三个不同的 URL 值的 url 域: Java、ECMAScript、内嵌的 ECMAScript:
Script { field SFBool start url [ "http://foo.com/fooBar.class", "http://foo.com/fooBar.js", "ecmascript:function start(value, timestamp) { ... }" ] }
在以上的例子中,当 Script 节点接受到一个 start 事件时,将执行 url 域中发现的某个节点。第一选择是 Java 平台字节代码,第二选择是 ECMAScript 代码,第三个选择是内嵌的 ECMAScript 代码。URL 域中多个值之间的优先选择顺序见 9.2.1, URLs。
由 Script 节点接受到的事件将被传递到脚本中适当的脚本语言方法。方法的名称依赖于使用的语言类型。在某些情况下,它和域的名称相同;另外的一些情况下,它产生产生一个对应所有事件的回调方法(细节参见脚本语言附件)。方法由两个参数传输:事件值和时间戳。
Script 节点的域和脚本语言方法相关。事件可以被路由到 Script 节点,Script 节点的域可以被路由到其它节点的域。其它的可访问此 Script 节点的 Script 节点可以按照访问其它节点一样访问此 Script 节点(见 29.2.4, Scripts with direct outputs)。
推荐用户定义的 Script 节点中的域或事件命名遵循 2.[I19775-2] 中描述的命名约定。
域的值可读取或写入,对于不同的方法调用来说域的值都是持久保存的,域的改变可通过它的更新方法通知到节点。域类型的更多信息见 5, 域类型参考 Field type reference。
X3DScriptNode : X3DChildNode,X3DURLObject { }
这个抽象类型是所有脚本节点的基本类型。
Script : X3DScriptNode { MFString [in,out] url [] SFBool [] directOutput FALSE SFBool [] mustEvaluate FALSE # And any number of: fieldType [] fieldName fieldType [in] fieldName fieldType [out] fieldName fieldType [in,out] fieldName }
Script 节点用于为场景中的行为编程。Script 节点一般:
每个脚本语言都有一个相关的由 url 域引用的程序设计语言代码,通过执行此代码可以实现 Script 节点的功能。这个代码在以下的描述中用 “脚本” 来引用。url 域的细节见 9.2.1, URLs。
浏览器并不一定需要支持任何一种语言规格。脚本语言的详细信息在 29.2, 概念 Concepts 中描述. 但是如果浏览器支持某种语言绑定,就应当相应的语言绑定规格。
某些时候在脚本接受到第一个事件前应被初始化(执行任何语言相关或用户定义的 initialize()
)。脚本能接受并处理发送到此脚本的事件。
每个能接收的事件应事先在 Script
节点中声明,声明所用的语法和原形定义中使用的语法相同:
eventIn type name
type(类型)可以为任何标准 X3D 域(定义见 5, 域类型参考 Field type reference)。Name(名称)应是一个此脚本中唯一的标识符。
Script 节点能产生对应输入事件的事件。每个能产生的事件应事先在 Script 节点中声明,声明所用的语法和原形定义中使用的语法相同:
eventOut type name
如果 Script 节点的 mustEvaluate 域为 FALSE,浏览器可以延迟向脚本发送输入事件,直到浏览器需要脚本输出时才发送。如果 mustEvaluate
域为
TRUE
,浏览器应尽可能快的向脚本发送输入事件,而不管是否需要输出。mustEvaluate 域只在
Script 节点对浏览器有未知效果(例如跨网络发送信息)时被设置为 TRUE
。否则将导致性能降低。
一旦脚本能存取一个 X3D 节点(经由 SFNode 或 MFNode 值存取,其中此 SFNode 或 MFNode 位于 Script
节点域中或是从一个事件的属性中传递过来的),脚本就能读取此节点域的内容。如果
Script 节点的 directOutput 域为 TRUE
,脚本也可以向它能存取的节点直接发送事件,也能动态地建立或打断路由。如果 directOutput
为 FALSE(缺省值)
,脚本只能通过自身的域来发送事件以影响场景的其它部分。如果 directOutput
为 FALSE
且脚本直接向其能存取的节点发送事件,则结果不确定。
脚本能直接和 X3D 浏览器通信以取得诸如当前时间或当前场景 URL 之类的信息。这由使用的脚本语言规格的 API 严格定义。
Script 节点在场景图变换层级中的位置对其运作效果没有影响。例如,即使 Script 节点的父节点为一个 whichChoice 设置为 "-1" 的节点(即忽略子),Script 节点仍继续按规格运作(即接受和发送事件)。
Scripting 组件提供 表 29.2 中规定的一个支持级别(levels)。
翻译 m17 保留版权 如需转载请联系http://17de.com/x3d/