{"action":"created","comment":{"url":"https://api.github.com/repos/immersive-web/editor-collab/pulls/comments/221702764","pull_request_review_id":160416377,"id":221702764,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyMTcwMjc2NA==","diff_hunk":"@@ -0,0 +1,422 @@\n+# WebXR Device API Enivronment Tracking and Coordinate Systems\n+This document is a subsection of the master WebXR explainer document which can be found [here](explainer.md).  That document contains all the information you could possibly want about setting up a WebXR session, the render loop, and more.  Yet another document will cover how user input is surfaced in WebXR. This document, on the other hand, is focused specifically on a deep-dive into how WebXR can be used to track the users' environment for a stable, comfortable, and predictable experience that works on the widest range of XR hardware.\n+\n+## Introduction\n+- How Does Environment Tracking Work?\n+- Lots of different types of hardware out there that use different technologies to track the environment\n+- Main ones are:\n+  - Accelerometer-based\n+  - Outside-in\n+  - Inside-out\n+- Explain the fact that these tracking systems are EMULATIONS of the world based on the hardwares' understanding and that this actually changes constantly as the tracking systems process new information.  Especially in the case of inside-out tracking.\n+- Explain that these technologies each have tradeoffs to accomodate the nature of the fluxuating data\n+- Explain that one of the biggest challenges of WebXR is to design an API that bridges across all these disparate underlying technologies to provide an API that behaves predictably for developers.\n+- The key to this is enabling progressive enhancement (find link to this web-wide reference) and graceful degradation that (most) developers don't need to explictly handle\n+\n+## XRStage\n+- Explain the purpose of a XRStage\n+- Explain how this is a developer convenience and a short-hand to get desired and predictable behavior out of the underlying systems regardless of how the actual tracking system is implemented\n+- Explain that not all hardware will be able to provide support for all stage types, but that where possible, a best-effort emulation can be provided\n+- Cover what this means in terms of feature detection and when developers should/shouldn't rely on it\n+\n+| Type                | Subtype                        | Example |\n+| --------------------| ------------------------------ | ------- |\n+| `XRStationaryStage` | `{subtype:\"default\"}`          | Cockpit simulator |\n+| `XRStationaryStage` | `{subtype:\"floorAligned\"}`     | **EXAMPLE** |\n+| `XRStationaryStage` | `{subtype:\"positionDisabled\"}` | 360 photo/video viewer |\n+| `XRBoundedStage`    |                                | **EXAMPLE** |\n+| `XRUnboundedStage`  |                                | **EXAMPLE** |\n+\n+### Stationary Stages\n+A _stationary_ experience is one which does not require the user to move around in space.  This type of experience is guaranteed to work on all hardware, regardless of tracking technology. There are three types of _stationary_ experiences that can be specified by passing the appropriate `XRStationaryStageMode`.\n+\n+#### Default Mode\n+Developers building an experience like a cockpit simulator should initialize use an `XRStationaryStage` initialized with the `default` mode.  The stage will be initialized using the user's position and orientation at the time the stage is created. Even though the user will remain roughly stationary, `XRDevicePose` objects retrieved using an `XRStationaryStage` in this mode may include position information as well as rotation information, and developers should use these matricies as is.  For example, hardware which does not support 6DOF tracking (ex: GearVR) may still use neck-modeling to improve user comfort. Similarly, a user may lean side-to-side on a device with 6DOF tracking (ex: HTC Vive).\n+\n+```js\n+let xrSession = null;\n+let xrStage = null;\n+\n+function onSessionStarted(session) {\n+  xrSession = session;\n+  xrSession.createStage({ type:'stationary' }).then((stage) => {\n+    xrStage = stage;\n+  })\n+  .then(setupWebGLLayer)\n+  .then(() => {\n+    xrSession.requestAnimationFrame(onDrawFrame);\n+  });\n+}\n+```\n+\n+#### Floor Aligned Mode\n+Developers building an experience like EXAMPLE should use an `XRStationaryStage` intitialized with the `alignedToFloor` mode. The stage will be initialized using the user's X/Z position and orientation at the time the stage is created; `Y` will be initialized to the floor. As with the `default` mode, even though the user will remain roughly stationary, `XRDevicePose` objects retrieved using an `XRStationaryStage` in this mode may include position information as well as rotation information, and developers should use these matricies as is.\n+\n+```js\n+let xrSession = null;\n+let xrStage = null;\n+\n+function onSessionStarted(session) {\n+  xrSession = session;\n+  xrSession.createStage({ type:'stationary', subtype:'alignedToFloor' }).then((stage) => {\n+    xrStage = stage;\n+  })\n+  .then(setupWebGLLayer)\n+  .then(() => {\n+    xrSession.requestAnimationFrame(onDrawFrame);\n+  });\n+}\n+```\n+\n+Some XR hardware will be unable to determine the actual floor level and will instead use an emulated floor.  Developers wishing to explictly set the emulated floor height can do so by supplying the `emulatedFloorHeight` option in the `XRStationaryStageOptions` at creation time.\n+\n+#### Position Disabled Mode\n+Developers building an experience like a 360 degree photo or video viewer should use an `XRStationaryStage` initialized with the `positionDisabled` mode.  The stage will be initialized using the user's orientation at the time the stage is created.  `XRDevicePose` objects retrieved using an `XRStationaryStage` in this mode, will always report position at the origin.\n+\n+```js\n+let xrSession = null;\n+let xrStage = null;\n+\n+function onSessionStarted(session) {\n+  xrSession = session;\n+  xrSession.createStage({ type:'stationary', submode: 'positionDisabled' }).then((stage) => {\n+    xrStage = stage;\n+  })\n+  .then(setupWebGLLayer)\n+  .then(() => {\n+    xrSession.requestAnimationFrame(onDrawFrame);\n+  });\n+}\n+```\n+\n+### Bounded Stages\n+A _bounded_ experience is one in which a user moves around their physical environment to fully interact, but will not need to travel beyond a pre-established boundary.  A _bounded_ experience is similiar to a _unbounded_ experience in that both rely on XR hardware capable of tracking a users' locomotion.  However, _bounded_ experiences are explictly focused on nearby content which allows them to target XR hardware that requires a preconfigured play area as well as XR hardware able to track location freely.\n+\n+```js\n+let xrSession = null;\n+let xrStage = null;\n+\n+function onSessionStarted(session) {\n+  xrSession = session;\n+  xrSession.createStage({ type:'bounded' }).then((stage) => {\n+    xrStage = stage;\n+  })\n+  .then(setupWebGLLayer)\n+  .then(() => {\n+    xrSession.requestAnimationFrame(onDrawFrame);\n+  });\n+}\n+```\n+\n+Some XR hardware may optionally report bounds geometry within which the application should try to ensure that all content the user needs to interact with can be reached. This polygonal boundary represents a loop of points at the edges of the safe space. The points are given in a clockwise order as viewed from above, looking towards the negative end of the Y axis. The shape it describes is not guaranteed to be convex. The values reported are relative to the stage origin, but do not necessarily contain it. The `XRBoundedStage.boundsGeometry` attribute is null if the bounds are unavailable. Points in the `boundsGeometry` array must have a `y` value of `0` and a `w` value of `1`.\n+\n+```js\n+// Demonstrated here using a fictional 3D library to simplify the example code.\n+function createBoundsMesh() {\n+  boundsMesh.clear();\n+\n+  if (xrStage.boundsGeometry) {\n+    // Visualize the bounds geometry as 2 meter high quads\n+    let pointCount = xrStage.boundsGeometry.length;\n+    for (let i = 0; i < pointCount - 1; ++i) {\n+      let pointA = xrStage.boundsGeometry[i];\n+      let pointB = xrStage.boundsGeometry[i+1];\n+      boundsMesh.addQuad(\n+          pointA.x, 0, pointA.z, // Quad Corner 1\n+          pointB.x, 2.0, pointB.z) // Quad Corner 2\n+    }\n+    // Close the loop\n+    let pointA = xrStage.boundsGeometry[pointCount-1];\n+    let pointB = xrStage.boundsGeometry[0];\n+    boundsMesh.addQuad(\n+          pointA.x, 0, pointA.z, // Quad Corner 1\n+          pointB.x, 2.0, pointB.z) // Quad Corner 2\n+  } else {\n+    // No bounds geometry to visualize\n+    boundsMesh.clear();\n+  }\n+}\n+```\n+\n+Changes to the bounds while a session is active should be a relatively rare occurrence, but it can be monitored by listening for the frame of reference's `boundsgeometrychange` event.\n+\n+```js\n+xrStage.addEventListener('boundsgeometrychange', xrBoundedStageEvent => {\n+  createBoundsMesh();\n+});\n+```\n+\n+### Unbounded Stages\n+A _unbounded_ experience is one in which the user is able to freely move around their physical environment while virtual content stays (roughly) stable. An example of this sort of experience would be a campus tour or a whole-house renovation preview. These experiences explicitly require that the user be unbounded in their ability to walk around. \n+\n+```js\n+let xrSession = null;\n+let xrStage = null;\n+\n+function onSessionStarted(session) {\n+  xrSession = session;\n+  xrSession.createStage({ type:'unbounded' }).then((stage) => {\n+    xrStage = stage;\n+  })\n+  .then(setupWebGLLayer)\n+  .then(() => {\n+    xrSession.requestAnimationFrame(onDrawFrame);\n+  });\n+}\n+```\n+\n+As the user moves significant distances from where the `XRUnboundedStage` was created, developers will need to deal with the fact that floating point precision issues will be introduced.  When this is close to occurring, developers should create a new `XRUnboundedStage`,and use the `XRCoordinateSystem.getTransformTo()` method to reparent any nearby virtual object to the new stage.  However, practially speaking, large _unbounded_ experiences will often segment app/game assets and logic into descrete map segments and, depending on map segment size, this may also be an opportune time to create a new `XRUnboundedStage`.\n+\n+When building a _unbounded_ experience, developers may choose to also create `XRAnchor` objects to act as parents for virtual content that must remain more permanently locked to an exact physical location.  For more information on `XRAnchors`, see THIS OTHER DOCUMENT.\n+\n+## Considerations When Using XRStages\n+Now that the Stage types have all been explained more thoroughly, here are some things that you'll need to know about putting your knowledge into practice.\n+\n+### Inline vs. Immersive \n+* Put an explanation here about the privacy/security limitations on `inline` sessions (once I figure out what we'd actually agreed on...)\n+* By default an `inline` session will be able to create an `XRStationaryStage`.  However, it may not be able to get pose data (based on the bullet above)\n+* Do we want to allow inline sessions to use the same pattern as described in the section on \"Ensuring hardware compatibility\"?  If so, what does user consent look like?\n+* Because most inline sessions will not support tracking position, developers are encourage to use pointer input to generate a transform that can be multiplied into the root of their scene.\n+\n+### Inline Experiences Without Tracking\n+Some XR devices, such as PCs with attached HMDs, will be unable to report any pose data in an `inline` session.  Additionally, some `inline` experiences explicitly want tracking information disabled, such as a furniture viewer that will use pointer data to rotate the furniture.  Under both of these situations, there is no `XRStage` needed.  Passing `null` into `getDevicePose` will retrive an `XRDevicePose` whose `poseModelMatrix` and all matrices returnd by `getViewMatrix` set to the identity matrix.  Developers are then free to multiply in whatever transform they choose for their rendering.\n+\n+### Ensuring hardware compatibility\n+It is strongly encouraged that developers build their experiences to target the breadth of XR hardware.  As such, when using an `XRBoundedStage` or an `XRUnboundedStage` developers are encouraged to provide a fallback experience that will work on hardware that does not support necessary tracking technology.\n+\n+```js\n+let xrSession = null;\n+let xrStage = null;\n+\n+function onSessionStarted(session) {\n+  xrSession = session;\n+  xrSession.createStage({ type:'unbounded' }).then((stage) => {\n+    xrStage = stage;\n+  })\n+  .catch(() => {\n+    // Build an appropriate fallback experience if possible\n+    xrSession.createStage({ type:'stationary' }).then((stage) => {\n+      xrStage = stage;\n+    });\n+  })\n+  .then(setupWebGLLayer)\n+  .then(() => {\n+    xrSession.requestAnimationFrame(onDrawFrame);\n+  });\n+}\n+```\n+Most sites should be able to provide a reasonable fallback on devices without the ideal tracking technology.  In fact, in many cases this fallback will behave similarly to the `inline` preview experience.  However, for some sites this will not be possible and under those circumstances, it is preferrable for the user to have the session creation reject rather than having them enter immersive mode only to immediately exit.\n+\n+```js\n+function beginImmersiveSession() {\n+  xrDevice.requestSession({ immersive: true,  requiredStageType:'unbounded' })\n+      .then(onSessionStarted)\n+      .catch(err => {\n+        // Error will indicate tracking mismatch\n+      });\n+}\n+```\n+\n+### Floor Alignment Compatibility\n+* Explain that floor-alignment is a bit trickier on inside-out tracking hardware\n+* Some platforms may allow the establishment of a \"known-space\" that is repeatably usable, but others may not (also there may be a security consideration here?)\n+* On platforms that don't support this intrinsically, the UA may choose to create a UI for allowing users to select the floor origin they would like to use for the stage creation\n+* Some UAs will choose not to implement this functionality.  Thankfully, this can be polyfilled if the request is rejected with an error code indicating the reason accurately.  The polyfill will draw it's own UI for selecting this floor origin using an `XRUnboundedStage` and dropping an `XRAnchor` at the user selected origin.\n+* As such, this is one of the main reasons that `XRStage` creation is asynchronous rather than done via constructor\n+\n+### Body-locked elements\n+It is sometimes desirable to build 3D UI elements that are drawn at a fixed distance from the user but locked in orientation.  For example, a control panel that should float a comfortable distance from a user's left hand.  As a convenience when building these UI affordances, developers may parent virtual objects to the `XRUser.bodyLockedCoordinateSystem`.  As the user rotates, the developer can either choose to leave these objects in place or animate them to gently follow the user's rotation.  As the user walks around, the objects will automatically follow them.\n+\n+### Transitioning between XRStages\n+It is expected that developers will often choose to preview `immersive` experiences with a similar experience `inline`.  In this situation, users often expect to see the scene from the same perspective when they make the transition from `inline` to `immersive`. In most cases, developers can accomplish this by computing the transform between the user and the virtual object that has the user's attention in the previous `XRSession`.  When the new `XRSession` is initialized, the same transform can be applied to the virtual object for its intital location on the new `XRStage`.","path":"environment-explainer.md","position":231,"original_position":231,"commit_id":"7e9cd7686b5e983f0043c58dc327c51e676529e4","original_commit_id":"7e9cd7686b5e983f0043c58dc327c51e676529e4","user":{"login":"NellWaliczek","id":21128176,"node_id":"MDQ6VXNlcjIxMTI4MTc2","avatar_url":"https://avatars2.githubusercontent.com/u/21128176?v=4","gravatar_id":"","url":"https://api.github.com/users/NellWaliczek","html_url":"https://github.com/NellWaliczek","followers_url":"https://api.github.com/users/NellWaliczek/followers","following_url":"https://api.github.com/users/NellWaliczek/following{/other_user}","gists_url":"https://api.github.com/users/NellWaliczek/gists{/gist_id}","starred_url":"https://api.github.com/users/NellWaliczek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NellWaliczek/subscriptions","organizations_url":"https://api.github.com/users/NellWaliczek/orgs","repos_url":"https://api.github.com/users/NellWaliczek/repos","events_url":"https://api.github.com/users/NellWaliczek/events{/privacy}","received_events_url":"https://api.github.com/users/NellWaliczek/received_events","type":"User","site_admin":false},"body":"I think I get what you're saying... do you mean that objects on a bounded stage might always need to be \"front' for whatever front is?  ","created_at":"2018-10-01T18:03:08Z","updated_at":"2018-10-01T18:03:08Z","html_url":"https://github.com/immersive-web/editor-collab/pull/1#discussion_r221702764","pull_request_url":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/immersive-web/editor-collab/pulls/comments/221702764"},"html":{"href":"https://github.com/immersive-web/editor-collab/pull/1#discussion_r221702764"},"pull_request":{"href":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1"}},"in_reply_to_id":221467924},"pull_request":{"url":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1","id":216484446,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE2NDg0NDQ2","html_url":"https://github.com/immersive-web/editor-collab/pull/1","diff_url":"https://github.com/immersive-web/editor-collab/pull/1.diff","patch_url":"https://github.com/immersive-web/editor-collab/pull/1.patch","issue_url":"https://api.github.com/repos/immersive-web/editor-collab/issues/1","number":1,"state":"open","locked":false,"title":"First sketch of an approach for rationalizing XRFrameOfReference, XRCoordinateSystem and the rest","user":{"login":"NellWaliczek","id":21128176,"node_id":"MDQ6VXNlcjIxMTI4MTc2","avatar_url":"https://avatars2.githubusercontent.com/u/21128176?v=4","gravatar_id":"","url":"https://api.github.com/users/NellWaliczek","html_url":"https://github.com/NellWaliczek","followers_url":"https://api.github.com/users/NellWaliczek/followers","following_url":"https://api.github.com/users/NellWaliczek/following{/other_user}","gists_url":"https://api.github.com/users/NellWaliczek/gists{/gist_id}","starred_url":"https://api.github.com/users/NellWaliczek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NellWaliczek/subscriptions","organizations_url":"https://api.github.com/users/NellWaliczek/orgs","repos_url":"https://api.github.com/users/NellWaliczek/repos","events_url":"https://api.github.com/users/NellWaliczek/events{/privacy}","received_events_url":"https://api.github.com/users/NellWaliczek/received_events","type":"User","site_admin":false},"body":"1. You might notice about this PR is that it's a TON of text.  Sorry!  If we actually take this approach, I'm strongly considering dividing the official PRs into much smaller chunks so that the wider group can actually process it bit by bit.  You, however, get the whole shebang today :)\r\n\r\n1. I tried to start off by capturing the things that seemed like \"aha!\" moments for folks in the room yesterday through the document structure and prose (though much of it not fleshed out yet).  I used this as the guidance to myself for how to break down the problem in terms of API design as I went along.  However, even if the API signatures turn out to be the wrong approach, I'm feeling pretty good about the logical breakdown and would ask that we focus more on that part than the exact signatures for initial feedback.\r\n\r\n1. I maybe sorta stole the term \"Stage\" to replace the term \"FrameOfReference\" as part of my refactoring things.  I don't know if that will give you an allergic reaction, and I don't feel *that* strongly about it but it seemed reasonable at the time.  Hopefully, my use of the term \"Local\" won't be a problem for Artyom either? \r\n\r\n1. Speaking of Artyom's request, I *think* I've covered it adequately, but I need to go back through the issue he posted and double check more thoroughly.  I might need to add a function or event or something to the XRLocalStage type to allow it to be reset.\r\n\r\n1.  I didn't yet examine what it would mean to expose 6DOF tracking feature detection as part of session initiation, but I'm starting to lean very strongly towards that needing to be possible.  As you'll see, the initialization of the XRLocalStage and the XRWorldStage could otherwise be fairly wonky and it would be really unfortunate to setup the whole session only to bail out at that point.\r\n\r\n1. I really don't know if the constructor pattern is the right approach.  I was really more focusing on the functionality division between XRStage types, and more or less randomly picked the constructor pattern.  As I note, though, am concerned that it would be weird to have an XRStage creatable if there's no XRSession.  But that starts to open up a whole new can of worms (which maybe you're already considering as part of your exploration to remove XRDevice) about whether or not `navigator.xr` should have an `activeSession` property?  Ugh.\r\n\r\n1. Relatedly, I need to go back through the whole proposal and make sure it's not totally borked for inline sessions.  Rather than hold the sketch back, I'm sending it over to you now though.\r\n\r\n1. I'm still not totally thrilled with the shape of the XRLocalStage options.  It feels like we might end up in one of those situations where developers would need to chain too many try/catch blocks together.  Not sure.\r\n\r\n1. I snuck in a couple more forward-looking explorations at the bottom to sanity check the general approach.  Obviously don't take any of that part too seriously.  Although, I will admit I am now swinging strongly towards the camp of needing to include XRAnchor as part of the initial WebXR 1.0 to make sure we actually have this API shape solidly buttoned up and extensible.\r\n\r\nAnyway, I'm looking forward to hearing your initial thoughts about this approach.  Hopefully it's not too insane a proposal?","created_at":"2018-09-19T00:52:03Z","updated_at":"2018-10-01T18:03:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4bc9db8bfdb20092157feaa709c7441c8f33f522","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1/commits","review_comments_url":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1/comments","review_comment_url":"https://api.github.com/repos/immersive-web/editor-collab/pulls/comments{/number}","comments_url":"https://api.github.com/repos/immersive-web/editor-collab/issues/1/comments","statuses_url":"https://api.github.com/repos/immersive-web/editor-collab/statuses/7e9cd7686b5e983f0043c58dc327c51e676529e4","head":{"label":"immersive-web:coordinate-systems-take1","ref":"coordinate-systems-take1","sha":"7e9cd7686b5e983f0043c58dc327c51e676529e4","user":{"login":"immersive-web","id":34385910,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0Mzg1OTEw","avatar_url":"https://avatars3.githubusercontent.com/u/34385910?v=4","gravatar_id":"","url":"https://api.github.com/users/immersive-web","html_url":"https://github.com/immersive-web","followers_url":"https://api.github.com/users/immersive-web/followers","following_url":"https://api.github.com/users/immersive-web/following{/other_user}","gists_url":"https://api.github.com/users/immersive-web/gists{/gist_id}","starred_url":"https://api.github.com/users/immersive-web/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/immersive-web/subscriptions","organizations_url":"https://api.github.com/users/immersive-web/orgs","repos_url":"https://api.github.com/users/immersive-web/repos","events_url":"https://api.github.com/users/immersive-web/events{/privacy}","received_events_url":"https://api.github.com/users/immersive-web/received_events","type":"Organization","site_admin":false},"repo":{"id":149317405,"node_id":"MDEwOlJlcG9zaXRvcnkxNDkzMTc0MDU=","name":"editor-collab","full_name":"immersive-web/editor-collab","private":false,"owner":{"login":"immersive-web","id":34385910,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0Mzg1OTEw","avatar_url":"https://avatars3.githubusercontent.com/u/34385910?v=4","gravatar_id":"","url":"https://api.github.com/users/immersive-web","html_url":"https://github.com/immersive-web","followers_url":"https://api.github.com/users/immersive-web/followers","following_url":"https://api.github.com/users/immersive-web/following{/other_user}","gists_url":"https://api.github.com/users/immersive-web/gists{/gist_id}","starred_url":"https://api.github.com/users/immersive-web/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/immersive-web/subscriptions","organizations_url":"https://api.github.com/users/immersive-web/orgs","repos_url":"https://api.github.com/users/immersive-web/repos","events_url":"https://api.github.com/users/immersive-web/events{/privacy}","received_events_url":"https://api.github.com/users/immersive-web/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/immersive-web/editor-collab","description":"Scratchpad for WebXR spec editor collaboration. Contents of this repo are not to be taken as spec proposals.","fork":false,"url":"https://api.github.com/repos/immersive-web/editor-collab","forks_url":"https://api.github.com/repos/immersive-web/editor-collab/forks","keys_url":"https://api.github.com/repos/immersive-web/editor-collab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/immersive-web/editor-collab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/immersive-web/editor-collab/teams","hooks_url":"https://api.github.com/repos/immersive-web/editor-collab/hooks","issue_events_url":"https://api.github.com/repos/immersive-web/editor-collab/issues/events{/number}","events_url":"https://api.github.com/repos/immersive-web/editor-collab/events","assignees_url":"https://api.github.com/repos/immersive-web/editor-collab/assignees{/user}","branches_url":"https://api.github.com/repos/immersive-web/editor-collab/branches{/branch}","tags_url":"https://api.github.com/repos/immersive-web/editor-collab/tags","blobs_url":"https://api.github.com/repos/immersive-web/editor-collab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/immersive-web/editor-collab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/immersive-web/editor-collab/git/refs{/sha}","trees_url":"https://api.github.com/repos/immersive-web/editor-collab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/immersive-web/editor-collab/statuses/{sha}","languages_url":"https://api.github.com/repos/immersive-web/editor-collab/languages","stargazers_url":"https://api.github.com/repos/immersive-web/editor-collab/stargazers","contributors_url":"https://api.github.com/repos/immersive-web/editor-collab/contributors","subscribers_url":"https://api.github.com/repos/immersive-web/editor-collab/subscribers","subscription_url":"https://api.github.com/repos/immersive-web/editor-collab/subscription","commits_url":"https://api.github.com/repos/immersive-web/editor-collab/commits{/sha}","git_commits_url":"https://api.github.com/repos/immersive-web/editor-collab/git/commits{/sha}","comments_url":"https://api.github.com/repos/immersive-web/editor-collab/comments{/number}","issue_comment_url":"https://api.github.com/repos/immersive-web/editor-collab/issues/comments{/number}","contents_url":"https://api.github.com/repos/immersive-web/editor-collab/contents/{+path}","compare_url":"https://api.github.com/repos/immersive-web/editor-collab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/immersive-web/editor-collab/merges","archive_url":"https://api.github.com/repos/immersive-web/editor-collab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/immersive-web/editor-collab/downloads","issues_url":"https://api.github.com/repos/immersive-web/editor-collab/issues{/number}","pulls_url":"https://api.github.com/repos/immersive-web/editor-collab/pulls{/number}","milestones_url":"https://api.github.com/repos/immersive-web/editor-collab/milestones{/number}","notifications_url":"https://api.github.com/repos/immersive-web/editor-collab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/immersive-web/editor-collab/labels{/name}","releases_url":"https://api.github.com/repos/immersive-web/editor-collab/releases{/id}","deployments_url":"https://api.github.com/repos/immersive-web/editor-collab/deployments","created_at":"2018-09-18T16:14:33Z","updated_at":"2018-09-28T21:23:51Z","pushed_at":"2018-09-29T18:19:35Z","git_url":"git://github.com/immersive-web/editor-collab.git","ssh_url":"git@github.com:immersive-web/editor-collab.git","clone_url":"https://github.com/immersive-web/editor-collab.git","svn_url":"https://github.com/immersive-web/editor-collab","homepage":null,"size":1632,"stargazers_count":5,"watchers_count":5,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":4,"license":{"key":"other","name":"NOASSERTION","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":4,"watchers":5,"default_branch":"master"}},"base":{"label":"immersive-web:master","ref":"master","sha":"a378b66195675d45f99695e5299b8651917f56ec","user":{"login":"immersive-web","id":34385910,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0Mzg1OTEw","avatar_url":"https://avatars3.githubusercontent.com/u/34385910?v=4","gravatar_id":"","url":"https://api.github.com/users/immersive-web","html_url":"https://github.com/immersive-web","followers_url":"https://api.github.com/users/immersive-web/followers","following_url":"https://api.github.com/users/immersive-web/following{/other_user}","gists_url":"https://api.github.com/users/immersive-web/gists{/gist_id}","starred_url":"https://api.github.com/users/immersive-web/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/immersive-web/subscriptions","organizations_url":"https://api.github.com/users/immersive-web/orgs","repos_url":"https://api.github.com/users/immersive-web/repos","events_url":"https://api.github.com/users/immersive-web/events{/privacy}","received_events_url":"https://api.github.com/users/immersive-web/received_events","type":"Organization","site_admin":false},"repo":{"id":149317405,"node_id":"MDEwOlJlcG9zaXRvcnkxNDkzMTc0MDU=","name":"editor-collab","full_name":"immersive-web/editor-collab","private":false,"owner":{"login":"immersive-web","id":34385910,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0Mzg1OTEw","avatar_url":"https://avatars3.githubusercontent.com/u/34385910?v=4","gravatar_id":"","url":"https://api.github.com/users/immersive-web","html_url":"https://github.com/immersive-web","followers_url":"https://api.github.com/users/immersive-web/followers","following_url":"https://api.github.com/users/immersive-web/following{/other_user}","gists_url":"https://api.github.com/users/immersive-web/gists{/gist_id}","starred_url":"https://api.github.com/users/immersive-web/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/immersive-web/subscriptions","organizations_url":"https://api.github.com/users/immersive-web/orgs","repos_url":"https://api.github.com/users/immersive-web/repos","events_url":"https://api.github.com/users/immersive-web/events{/privacy}","received_events_url":"https://api.github.com/users/immersive-web/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/immersive-web/editor-collab","description":"Scratchpad for WebXR spec editor collaboration. Contents of this repo are not to be taken as spec proposals.","fork":false,"url":"https://api.github.com/repos/immersive-web/editor-collab","forks_url":"https://api.github.com/repos/immersive-web/editor-collab/forks","keys_url":"https://api.github.com/repos/immersive-web/editor-collab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/immersive-web/editor-collab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/immersive-web/editor-collab/teams","hooks_url":"https://api.github.com/repos/immersive-web/editor-collab/hooks","issue_events_url":"https://api.github.com/repos/immersive-web/editor-collab/issues/events{/number}","events_url":"https://api.github.com/repos/immersive-web/editor-collab/events","assignees_url":"https://api.github.com/repos/immersive-web/editor-collab/assignees{/user}","branches_url":"https://api.github.com/repos/immersive-web/editor-collab/branches{/branch}","tags_url":"https://api.github.com/repos/immersive-web/editor-collab/tags","blobs_url":"https://api.github.com/repos/immersive-web/editor-collab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/immersive-web/editor-collab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/immersive-web/editor-collab/git/refs{/sha}","trees_url":"https://api.github.com/repos/immersive-web/editor-collab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/immersive-web/editor-collab/statuses/{sha}","languages_url":"https://api.github.com/repos/immersive-web/editor-collab/languages","stargazers_url":"https://api.github.com/repos/immersive-web/editor-collab/stargazers","contributors_url":"https://api.github.com/repos/immersive-web/editor-collab/contributors","subscribers_url":"https://api.github.com/repos/immersive-web/editor-collab/subscribers","subscription_url":"https://api.github.com/repos/immersive-web/editor-collab/subscription","commits_url":"https://api.github.com/repos/immersive-web/editor-collab/commits{/sha}","git_commits_url":"https://api.github.com/repos/immersive-web/editor-collab/git/commits{/sha}","comments_url":"https://api.github.com/repos/immersive-web/editor-collab/comments{/number}","issue_comment_url":"https://api.github.com/repos/immersive-web/editor-collab/issues/comments{/number}","contents_url":"https://api.github.com/repos/immersive-web/editor-collab/contents/{+path}","compare_url":"https://api.github.com/repos/immersive-web/editor-collab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/immersive-web/editor-collab/merges","archive_url":"https://api.github.com/repos/immersive-web/editor-collab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/immersive-web/editor-collab/downloads","issues_url":"https://api.github.com/repos/immersive-web/editor-collab/issues{/number}","pulls_url":"https://api.github.com/repos/immersive-web/editor-collab/pulls{/number}","milestones_url":"https://api.github.com/repos/immersive-web/editor-collab/milestones{/number}","notifications_url":"https://api.github.com/repos/immersive-web/editor-collab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/immersive-web/editor-collab/labels{/name}","releases_url":"https://api.github.com/repos/immersive-web/editor-collab/releases{/id}","deployments_url":"https://api.github.com/repos/immersive-web/editor-collab/deployments","created_at":"2018-09-18T16:14:33Z","updated_at":"2018-09-28T21:23:51Z","pushed_at":"2018-09-29T18:19:35Z","git_url":"git://github.com/immersive-web/editor-collab.git","ssh_url":"git@github.com:immersive-web/editor-collab.git","clone_url":"https://github.com/immersive-web/editor-collab.git","svn_url":"https://github.com/immersive-web/editor-collab","homepage":null,"size":1632,"stargazers_count":5,"watchers_count":5,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":4,"license":{"key":"other","name":"NOASSERTION","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":4,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1"},"html":{"href":"https://github.com/immersive-web/editor-collab/pull/1"},"issue":{"href":"https://api.github.com/repos/immersive-web/editor-collab/issues/1"},"comments":{"href":"https://api.github.com/repos/immersive-web/editor-collab/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/immersive-web/editor-collab/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/immersive-web/editor-collab/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/immersive-web/editor-collab/statuses/7e9cd7686b5e983f0043c58dc327c51e676529e4"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"NellWaliczek"}}