Virtual World Framework – Addt’l Notes to Add VWF Introductory Notes (from intro session) Dynamic Plant Model (DPM) – complex model, ex. Nuclear plant system – don’t want to write javascript to handle model, proxy it in as a client Levels: o Kernal o Model: Script o Model: Scene o Model: Properties – Switch Lamp Click goes into a model, filters down to kernel All external events bounce off the reflection server (with timestamp) A DPM would be an additional web service to bounce off reflector Transform index.vwf into an application – transform browser into a vwf application running in a browser Drivers o One expresses data from 3D models (collada files) o Web service driver – does proxy into remote server Kernal brings in each driver and asks “can you handle this event?” ex. Mouse click o Changes state of switch, sends to kernel and changes are propagated through scene manager to be changed o Application sees a method was called and properties changed Views – accepts canvas mouse click – method call to kernel, pointerClick on this node, sent to reflector and sent to clients to internally execute Kernal Models – Switch, Lamp Code – o Lib/ server code is here – starts in vwf.rb, reflector in vwf server o Public/ application files – finds index.vwf.yaml (encoded in json or yaml) o Support/client/lib – loads index.html Vwf.js is kernel View-.js are drivers Vwf/model.js, model/glge.js, model/object.js – Models Async.js – managing callbacks Radio example: o Application side – public directory – index.vwf.yaml – indentation important o Dashes mean it’s an array – script array example o References are local to file, relative path o XML glge scene manager file o Children – can be defined in yaml and bind to a model defined in XML Children can have properties, and can be a shortcut notation or define set function and value Arbitrary javascript for child or application overall, depending on indentation Initialize – timing issue work around – ensure the positions, etc properties are initially set, controls order things happen Naming convention – need to be able to determine whether it’s a component or not o http://vwf.example.com/types/node3 (without extension) local cache on server o appscene.vwf relative to path Load order: treats each vwf file as a directory, puts all client directory files automatically (index.html) o Index.html – loads jquery and other libraries o Kernel file – vwf.js o Require.js library – module loader o Loads drivers o Call vwf.initialize – configuration of drivers (here you could attach drivers to certain parts of the graph – on initialize configuration) o Stylesheets for admin view o Custom HTML style, jquery content – vwf.html file – describes page, imported when application loaded, dropped into body Vwf.js o Keeps track of models and views o Initialize function – takes in models and views to initialize o Parses any URL arguments o Constructs each model and view o Jumps to ready function o Establishes socket connection o Sets up callback function to handle messages o Handles incoming and outgoing messages o Tick – how it handles time o Kernal functions – createNode, addChild, removeChild, setProperty, createProperty, etc o 2 APIs Kernal API – coming into the kernel, createNode, createProperty, callMethod Kernal goes to each model, and says “setting property – do you want to handle it?” Model API – settingProperty, actively doing, “gettingProperty” View – past tense of property name, “gotProperty” Model Drivers o Modules – call global function define Extending model object with object Initialize – in kernel, define model api functions that the kernel will invoke – active form “creatingNode”, goes to get object based on nodeId, remember ID and source, create new hash for properties If something is returned, kernel will quit asking, otherwise will keep bubbling it up o Object driver – object.js Default driver o Javascript driver – javascript.js CreatingProperty – needs ability to invoke getters and setters o Glge.js – current state, view and model code mixed up together Eventually get to table based scripting – using text implementations – 80% of scripting done that way, better for people who don’t know programming Email Notes model/view api assistance - configurations - maintains ids - has own node ids and requires translation - can orphan - can maintain a reference to a node not (yet) attached to a parent - can prototype - can mirror the prototype graph and cow properties - cares about - sub-tree rooted at source type, eg, node[@type=’model/x-collada’]//* - nodes with scripts, eg, node[script] - partial api on a node, eg, - property gets, but not sets (exposes read-only property) - methods, but no properties or events Notes on components & types - Will simplify component specifications. - Typical minimum currently: { extends: “.../scene”, source: “something.unity3d”, type: “application/vnd.unity” } - Becomes: { source: “something.unity3d” } - Or even, “something.unity3d” - Allow component URIs to resources other than .vwf files. Assign base (“extends”) using mime type mapping. - “abc.vwf” => { extends: “abc.vwf” } - “…/scene.vwf” =? { extends: “…/scene.vwf” } - “something.unity3d” => { source: “something.unity3d” } => { extends: “…/scene”, source: “something.unity3d” } - source => type => extends TODO Reflector Timeline - Play/pause/stop. Playback rates (inherited, modified by hierarchy?) Sync - Client sync, resync. Maintain state on server. Pass to client when joining. - Client resync. Track client latency reduce to minimum. If a client lags behind, purge and resync from current state. - Merge-based state updates. Update system state based on locality of changes, not strictly ordered. Like a version control system, time-clocks, Google Wave. Admin - Admin interface. Show applications, instances, users. Invite, kick, ban users. Show time and message stream. Play/pause/stop. Authentication is separate from application. Is a separate Rack app? Component API - Component APIs: node, node2, node3 (visible, transforms, materials, animations), camera - “Initialize” script call. - Behaviors (implements) in addition to prototype (extends). - Bubble up events Scripting - JavaScript scripting. Getters, setters, events, on method, etc. - Table-based scripting. Same language as for describing lesson progress. - JavaScript prototype delegation properties, methods. - JavaScript event listeners. Get Evented Programming right - Handle events, callbacks properly throughout vwf. For VWF API (createNode with delayed loads, etc.) and for interactions with models and views (or only for models since views are not synchronous?). Sequences of calls into vwf should return only when complete (but possibly via a callback) and should execute in order. - Calls into the view API deliver return values via callback. Model, View API (driver API) - Provide helper functionality in models and views to provide standard implementation for id mapping, resolving prototypes, and other common functions. - Remove any reference to vwf in models and views. Always route through the base model or view instance. - Separate GLGE into proper model and view pieces socket.io library - Support socket.io reconnections. Client should attempt to reconnect after the server connection is dropped. - Upgrade to current socket.io. Requires reworking ruby socket.io server. - Reduce socket.io client files to remove developer content. Locate proper source tracking updates. Map media types into component types - Auto-assign node types with help from drivers. Avoids all of the “extends node3”, etc. references for common cases. Drivers may indicate a node’s default type when the driver is binding to the node (eg, for a scene manager, an untyped child of a bound parent may be indicated as node3 if the parent in the scene has a child matching by name). - Drivers (or the server?) should provide a list of supported content types that can be treated as applications. - Determine the content type from the asset. Use OS’s assignment, configuration in server, or defaults in client, in that order. - Standard camera implementation. Provide a default camera implementation that doesn’t require any special application configuration. A raw asset should be usable as an application with reasonable default behavior. Provide orbit, walk, fly (which ones?). Allow application to configure or to provide specialized camera(s) that replace default. Should work the same for WebGL and Unity content. May also want to do something relevant for 2-D content (zoom, scroll, etc.—useful for svg, large images). - Allow component scripts to refer to files. Load dynamically. - Develop a succinct language for describing lesson progression. Should be a declarative version of the API that JavaScript has access to. Automatically handles delays & callbacks so that event sequences can be specified linearly. Support branching and merging for parallel actions. Use as a component scripting language too for simple actions (may handle majority of behavior scripting). - CoffeeScript Kernel - Proper node ids. IDs must be map between the same node and id on each client, but each client must assign IDs independently and in the face of arbitrary load order for delayed content. - Content binding. By path and/or other attributes. XPath-like queries. root.a.b, root.”a a”.b, root//b, root/*[@name=’a’]/b, root/*[@some-other-property-identifying-a=’whatever’]/b. As with Xpath, may select more than one at a time. - Resolve address, bind on reference - Develop a scheme for wrapping a UI on a component. Consider something like panels or blocks from web content management systems. Allow drivers to specify default UI wrappers with editors for the data they manage (somewhat like what vwf-view-html does). - Compose UI blocks to form a full scenario UI for the application (like FAPVplayer). - Lesson display and tracking. - Decide on names for: kernel (vwf), drivers (vwf-model-xxx, vwf-view-xxx), content (public/…) - All relative paths referenced by content files should be relative to the referencing item. Asset references from components should be relative to the component, and references within those should be relative to the asset, etc. - Verify URI escaping in server. Using encoded/decoded versions properly? - Authentication, authorization. Provide a login mechanism. Allow applications and instances to specify access controls. Move application instance tracking to a session cookie, remove instance id from URL, and provide invitation URLs to compensate. - Handle text encodings properly. Specifically, let the JSON decoder work with text containing a BOM. - Allow any accepted asset type as content index: index.vwf.template, index.dae, index.unity3d, etc. Search for any accepted asset type by extension if named resource is not found (http://vwf.example.com/path/to/content tries index.vwf[.template], index.asset if content is a directory then .../content.vwf[.template], content.asset)? - Break out “resource” field in reflection API? Most calls have one. Leaves parameters array exclusively for parameters. - Something with 3d css for lightweight 3d - Debugger for VWF scripts - Logging. Unify server and all clients. Record by level. Turn up/down by area (particular subsystem, component, etc.) Disable for release. Remove from JavaScript to remove string calculations even if not displayed and to reduce file size. - SCRIPT_NAME, REQUEST_PATH usage correct in server? - Server access to shared state must be thread aware? - Module loader. Be RequireJS (?) compliant. Use RequireJS. - Use script loader. Load driver-dependent scripts only when needed (eg, jQuery UI). - Missing API functions. removeChild(), deleteProperty(), etc. - JavaScript security settings for component scripts. Hide window, document, vwf. Set non-writable, etc. appropriately. - JavaScript “use warnings”. - Optimize calls to drivers: by content type (only 3-D nodes), node IDs (descendants of scene root), script type (only nodes with JavaScript), …. Driver specifies and updates dynamically. - vwf-model-object (vwf-model-node?) backstop driver to record node graph and property values if no other driver handles. - Driver priority of influence (vwf-model-glge has current answer for animated transform even though vwf-model-object has also recorded it) - Make a GLGE forks that is well-behaved for VWF. - Define specifications for good behavior for a VWF model (no state change other than directed by VWF stimulus, math, library standards), VWF view (no direct access manipulation of model). - Validate API calls across reflector, both client and server side. Delegate client-side by function invoked. - Application source order. Possible prioritization: from vwf.initialize(), in URI (?application=uri), from reflector, same location as index.html, selection dialog. Allow overriding what reflector would say if index.html was loaded from an application page (eg, which to choose from: http://vwf.example.com/path/to/application.vwf?application=http://other.host.com/other/application. vwf)? - Don’t reload a component when a load has already started but not yet completed. - Handle component and asset load failures. - Order of construction. Construct top-down, then initialize bottom-up? Or both bottom-up. Want to prevent reliance on parent during construction so that any child node may exist independently as a component. For a well-defined graph though, drivers would prefer to construct top down to avoid duplicate storage before node is attached. - Mock filesystem for tests. - Read me (github, Sinata-style introduction and overview). - Handle clients joining running sessions. Initialize with current node graph and property values instead of application default. - For animations, maintain playing/paused state, start time, pause time in properties for properly connecting new clients. - Transcendental consistency. - kernel.setProperty/getProperty (and other calls?) from a model should (optionally be able to?) begin the evaluation starting with the driver below the driver making the call. This is similar to the way that gets/sets originating in a javascript accessor function don’t start at the top. The motivation is vwf-viewglge (and presumably a future vwf/model/glge) wanting to getProperty() to get the initial values (originally sent with the createProperty) for playing/looping/speed to initialize the internals after a delayed load callback. (With proper callback handling, this specific case wouldn’t be necessary, but similar cases probably are.) Get/Set use cases: - Notes: - need to call on derived/deriving objects when property is changed on deriving/derived object? - look at get/set in JS defineProperty() for reference - move to property definition to keep property code with property initial value and main definition - also makes clear that the property must be declared there when only attaching get/set - allow property assignments to accept value and/or value+get+set hash - rename getter/setter to get/set since that’s familiar to JS defineProperty() users - Cases - none - set updates stored value, get returns stored value - notification - get and set are called but don’t affect the stored value - operates like none, except for side effects from get/set handlers - would like to not require handlers to return a value or explicitly set the internal value - transformation - set modifies the incoming value, to quantize, range limit, etc. - filtering - set rejects invalid values - the value isn’t set and no other setters or drivers are notified - aggregation - set redirects the value into one or more other properties, color into r/g/b, for example - get gathers the value from one or more other properties - no stored value in this case - no drivers are notified for the aggregated property since there is not value change - Considering prototypes - for js - assigning to derived searches the prototype chain for a get/set definition as for a search when getting a value - with a setter on base and no setter on derived, assigning to derived still invokes setter declared on base - with a setter on derived and a setter on base, assigning to derived invokes the setter on derived - assigning to base invokes the setter on base but not the setter on derived - without a setter on derived, assigning to derived without base as the prototype sets the value - after assigning base as derived’s prototype, derived’s value is suppressed and base’s setter surfaces at derived - anonymous (transform=) extends derived extends node3 (transform) Unity demoability - Prepackage Firefox portable with the required version of Unity player? - Find public Unity player content that will prompt to load the correct Unity player. - with proxy enabled: visit Unity content site; install or verify player - disable proxy; visit VWF Unity demo Component mockup (rough), shows: - child references as jQuery selectors and/or XPath queries - property initializers plain or with value, get, set - event declaration and handler manipulation - table-based scripting as a hash indexed by incoming event with an array of steps - changed event per property - nested declarative script with fork and join --extends: scene source: radio.xml type: model/x-glge properties: power: false otherpower: set: function( value ) { children["#indicator].properties.on = value } type? get: ... get script ... value: false events: power: ~ children: #switch: properties: on: false #indicator: properties: on: false scripts: - text: > function initialize() { properties.power = false; # script properties.power.set = function( value ) { children["#indicator].properties.on = value } # just one setter; only available to component properties.power.add( function( value ) { … } ) # every property has a changed event for use outside the component events.power.add( function( value ) { … } ) # explicit power changed event # events.power.remove( handler ), events.power.flush( context ) methods.something.add( function( … ) { … } ) # every method has an invoked event? probably not. } type: application/javascript - text switch.click: - children.["#switch"].rotateTo( "on" ) # plays animated transform - children.["#indicator"].on = true # executes when transform complete - events.power.fire( properties.power ) switchwithmorecomplicatedhandler["rotating-position-two"]: # non-alphanum event id - left: # fork into “left” and “right” paths running in parallel - step1 # “left” steps execute in sequence - step2 - step3 right: - stepA # “right” steps execute in sequence - stepB - sounds.complete.play() # join, then execute next step of main sequence type: application/vwfscript Technical overview notes: Block diagram of json/yaml path What server looks like block diagram Server variants: apache, ruby, node.js Overview of which & why - Node.js: lightweight, going quickly? - Ruby: middle weight - Apache: full infrastructure Three pieces to server: file, jsonp, reflector, application root magic All three running to same API. VMware, amazon images, boot disks Pretend to have all the stuff local even if it isn’t. Write that down. (Server application URL magic.) Email a live working world. How Unity fits in. How marshalling in and out works. Unity detailed implementation. View side only OK in VWF. Harder to expose too much Unity functionality down into VWF APIs. Fundamentally: graph of nodes with p, m, e. Import Collada into Unity running in parallel with GLGE. Unity in IE, GLGE in Chrome. Check Google plug-in to IE for WebGL support How to automatically install Unity or Google plug-in when first launching on IE? HTML snippet to paste into page to embed world That whole thing that I just did there with the duck and plane and timeline start/stop fast/slow and log. Do the application UI (sliders on demo pages). Source .dae from SketchUp pages directly from URL. Recursive embedding of worlds on faces of nodes in scenes. Separation of timelines when embedding instances of worlds. /path/to/component.vwf: { property1: value, p2: value } /path/to/hello.vwf: alert( “hello” ) <script src=”/path/to/component.vwf“></script> <script>{ property1: value, p2: value }</script> <script>alert( “hello” )</script> <script src=”/path/to/component.vwf?name=func“></script> <script>func() { return { property1: value, p2: value } }()</script> Diagram notes: - angles: - single-user: state machine, external inputs, internal state sequence, state is quantized, time is an external event - model/view: - state machine is programmed as objects (components) arranged in a graph, communicating through properties, messages, events - model is state machine, implemented as an amalgamation of drivers - view presents model state, injects external events, also implemented as an amalgamation of drivers - state machine - applications - engine is kernel + federation of drivers - state machine - view vs model - reflector Property accessor usage patterns: - notify: receive notification of set/get - set: ... do something ... ; this.property = value - limit: range limit or other validation - set: this.property = Math.max( 0, Math.min( value, 1 ) ) - proxy: act as a proxy for other properties - set: this.length = value.length ; this.unit = value / this.length - get: return this.unit * this.length - reject: prevent invalid assignments - set: if ( typeof value == "string" ) this.property = value Specifying set or get as null prevents writing and/or reading, respectively: - property - set: null - get: null Component specifications may be any of: - Object literal - URI to .vwf or other identifiable type: .dae, ... - JSON-encoded object (primarily for use in the single-user mode application= URI parameter) They may appear in: - extends, implements, child within a component specification - application=... parameter for single-user mode (URI or JSON-encoded only) - createNode() call Nodes inherit from their prototype: - source/type - specifying in a derived node replaces the value in the prototype - properties, methods, events - derived node's definitions augment those in the prototype - new name is a new definition - existing name overrides prototype's definition - how to delegate to overridden definition in prototype? - children - derived node's definitions augment - new name is a new definition - existing name configures definition from prototype - scripts - derived node's scripts augment the prototype