{"_id":"5b8469e2146f290003ee2511","category":{"_id":"5b8469e2146f290003ee24fe","version":"5b8469e2146f290003ee2585","project":"578c4badbd223d2000cc1441","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-07-18T21:08:45.730Z","from_sync":false,"order":3,"slug":"develop","title":"Basics"},"parentDoc":null,"user":"578c4a62bd223d2000cc143e","project":"578c4badbd223d2000cc1441","version":{"_id":"5b8469e2146f290003ee2585","project":"578c4badbd223d2000cc1441","__v":0,"forked_from":"5b74987b8326970003cfc12d","createdAt":"2018-04-23T20:03:35.726Z","releaseDate":"2018-04-23T20:03:35.726Z","categories":["5b8469e2146f290003ee24fb","5b8469e2146f290003ee24fc","5b8469e2146f290003ee24fd","5b8469e2146f290003ee24fe","5b8469e2146f290003ee24ff","5b8469e2146f290003ee2500","5b8469e2146f290003ee2501","5b8469e2146f290003ee2502","5b8469e2146f290003ee2503"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.10.0","version":"2.10.0"},"githubsync":"","__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-09-13T23:01:36.797Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":2,"body":"The ```<Viro*SceneNavigator>``` handles the transitions between ```<ViroScene>``` objects. It enables the 3D equivalent of a navigation stack. \n\nViro displays the scene at the top of the stack. To move to a new scene, simply push that scene onto the navigation stack. To return to the previous scene, pop the current scene off the stack. The Scene Navigator itself can always be retrieved for these operations via each Scene's ```sceneNavigator``` property.\n\nThe following is a simple example. Below we have a ```<ViroVRSceneNavigator>``` that renders a simple initial scene.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var FirstScene = require('./FirstScene');\\n\\nvar ViroSceneNav = React.createClass({\\n  render: function() {\\n    return (\\n      <ViroVRSceneNavigator\\n        initialScene={{\\n          scene: FirstScene,\\n        }}\\n      />\\n    );\\n  }\\n});\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nWhen the application is launched, the scene exported in FirstScene.js is displayed. Continuing the example, ```FirstScene``` is a simple scene with an image, shown below. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var SecondScene = require('./SecondScene');\\n\\nvar FirstScene = React.createClass({\\n  render: function() {\\n    return (\\n      <ViroScene>\\n        <ViroImage source={require('./res/image.jpg')} \\n                   position={[0, 0, -5]} \\n                   onClick={this._pushNextScene}/>            \\n      </ViroScene>\\n    );\\n  },\\n  \\n  _pushNextScene(){\\n     this.props.sceneNavigator.push({scene:SecondScene});\\n  },\\n});\\n\\nmodule.exports = FirstScene;\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nThe image has a click handler ```_pushNextScene()``` which, when pressed, pushes ```SecondScene``` onto the stack. Notice that the Scene Navigator is always available via ```this.props.sceneNavigator```.  \n\nWhen ```SecondScene``` is pushed onto the stack, it will be rendered until either another new scene is pushed onto the stack, or until it is popped off the stack via ```this.props.sceneNavigator.pop()```. \n\n**Important Note: **Ensure that you do not pop the last scene on the stack, this will result in a red screen with a \"Cannot pop below 0\" message in development and a crash in release!\n[block:api-header]\n{\n  \"title\": \"Jumping\"\n}\n[/block]\nIn addition to pushing and popping scenes, you can also ```jump``` between scenes.\n\n```Jump``` is used to quickly move from scene to scene on the navigation stack. If the scene we are jumping toward is already on the stack, we move it to the top, displaying it to the user. If the scene is not already in the stack, we push it to the top.\n\nJumping is useful for applications that frequently switch between a number of scenes. Jumping is also optimized to be faster than doing the same via push and pop.\n\nNote that to jump correctly, each scene requires a *scene key*. The scene key identifies the scene, enabling Viro to recognize when said scene is already on the stack so we can quickly jump to it.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var SecondScene = require('./SecondScene');\\n\\nvar FirstScene = React.createClass({\\n  render: function() {\\n    return (\\n      <ViroScene>\\n        <ViroImage source={require('./res/image.jpg')} \\n                   position={[0, 0, -5]} \\n                   onClick={this._jumpNextScene}/>            \\n      </ViroScene>\\n    );\\n  },\\n  \\n  _jumpNextScene(){\\n     this.props.sceneNavigator.jump(\\\"scene2\\\", {scene:SecondScene});\\n  },\\n});\\n\\nmodule.exports = FirstScene;\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Replacing\"\n}\n[/block]\nFinally, to simply replace the scene at the top of the stack with a different scene, use the ```replace``` method. Replace is useful for applications that have no need for a hierarchical scene stack, and instead simply swap out one scene for another at the root level.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var SecondScene = require('./SecondScene');\\n\\nvar FirstScene = React.createClass({\\n  render: function() {\\n    return (\\n      <ViroScene>\\n        <ViroImage source={require('./res/image.jpg')} \\n                   position={[0, 0, -5]} \\n                   onClick={this._replaceNextScene}/>            \\n      </ViroScene>\\n    );\\n  },\\n  \\n  _replaceNextScene(){\\n     this.props.sceneNavigator.replace({scene:SecondScene});\\n  },\\n});\\n\\nmodule.exports = FirstScene;\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Passing Props from Scene to Scene\"\n}\n[/block]\nAs with most mobile apps, you may also need to pass information through different experiences, or scenes. For example, if a user selects an item from a virtual menu to be then displayed in a newly pushed scene, your application may need to propagate additional information related to the selected item into the new scene. In Viro, there are 3 ways that you can pass information through scenes.\n\n**Option 1: Using passProps**\nIf you are looking to pass static properties to your next scene, you can use the *passProps* parameter within the scene navigator. This approach is great for providing individual scenes with static, unchanging parameters - the passProp **cannot be changed** once you push a scene with that prop! (To get around that you can use option #2 below.)\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// For your initial scene, you can populate passProps as part of \\n// the initialScene dictionary, using the following syntax:\\n<ViroARSceneNavigator \\n          apiKey=\\\"API_KEY_HERE\\\"\\n          initialScene={{\\n                      scene:InitialARScene, \\n          \\t\\t\\t\\t\\t\\tpassProps:{displayObject:true}\\n          }}/>\\n\\n// To Pass properties when pushing another scene, use the following syntax:\\nthis.props.sceneNavigator.jump(\\\"Shop\\\", {\\n    scene : require('./Shop'),\\n    passProps: {\\n        displayObject : true\\n    }\\n);\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nThen in our InitialARScene, you should be able to reference your value with **this.props.displayObject.**\n\n**Option 2: Using viroAppProps**\nThe scene navigator object is actually passed as a prop to each scene that you have. If you are using ViroSceneNavigator the prop is called **sceneNavigator**. If you are using ViroARSceneNavigator it's called **arSceneNavigator**. The navigators have a dictionary object called **viroAppProps** which you can use as global dictionary to store and pass values across your app. This can be used to maintain application state.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// For your initial scene, you treat viroAppProps as a \\n// global dictionary container with which to pass information.\\n<ViroARSceneNavigator \\n          apiKey=\\\"API_KEY_HERE\\\"\\n          initialScene={{scene:InitialARScene}}\\n          viroAppProps={{displayObject:false}}\\n        />\\n\\n// To pass information from the current scene to the next, simply\\n// reference the dictionary with the sceneNavigator that is passed\\n// to each scene.\\nthis.props.sceneNavigator.viroAppProps={displayObject:true};        \",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nThen in our InitialARScene, you should be able to check your value with **this.props.sceneNavigator.viroAppProps.displayObject.**\n\n\n**Option 3: Using Redux** \nGenerally, if you want props to span across multiple components I recommend using Redux to manage application state. This would mostly be the case for more involved and larger applications, where the above two solutions would not be sufficient, and most likely get out of hand pretty quickly the larger your application grows. More info here on Redux: https://medium.com/:::at:::jonlebensold/getting-started-with-react-native-redux-2b01408c0053","excerpt":"","slug":"scene-navigation","type":"basic","title":"Scene Navigation"}
The ```<Viro*SceneNavigator>``` handles the transitions between ```<ViroScene>``` objects. It enables the 3D equivalent of a navigation stack. Viro displays the scene at the top of the stack. To move to a new scene, simply push that scene onto the navigation stack. To return to the previous scene, pop the current scene off the stack. The Scene Navigator itself can always be retrieved for these operations via each Scene's ```sceneNavigator``` property. The following is a simple example. Below we have a ```<ViroVRSceneNavigator>``` that renders a simple initial scene. [block:code] { "codes": [ { "code": "var FirstScene = require('./FirstScene');\n\nvar ViroSceneNav = React.createClass({\n render: function() {\n return (\n <ViroVRSceneNavigator\n initialScene={{\n scene: FirstScene,\n }}\n />\n );\n }\n});", "language": "javascript" } ] } [/block] When the application is launched, the scene exported in FirstScene.js is displayed. Continuing the example, ```FirstScene``` is a simple scene with an image, shown below. [block:code] { "codes": [ { "code": "var SecondScene = require('./SecondScene');\n\nvar FirstScene = React.createClass({\n render: function() {\n return (\n <ViroScene>\n <ViroImage source={require('./res/image.jpg')} \n position={[0, 0, -5]} \n onClick={this._pushNextScene}/> \n </ViroScene>\n );\n },\n \n _pushNextScene(){\n this.props.sceneNavigator.push({scene:SecondScene});\n },\n});\n\nmodule.exports = FirstScene;", "language": "javascript" } ] } [/block] The image has a click handler ```_pushNextScene()``` which, when pressed, pushes ```SecondScene``` onto the stack. Notice that the Scene Navigator is always available via ```this.props.sceneNavigator```. When ```SecondScene``` is pushed onto the stack, it will be rendered until either another new scene is pushed onto the stack, or until it is popped off the stack via ```this.props.sceneNavigator.pop()```. **Important Note: **Ensure that you do not pop the last scene on the stack, this will result in a red screen with a "Cannot pop below 0" message in development and a crash in release! [block:api-header] { "title": "Jumping" } [/block] In addition to pushing and popping scenes, you can also ```jump``` between scenes. ```Jump``` is used to quickly move from scene to scene on the navigation stack. If the scene we are jumping toward is already on the stack, we move it to the top, displaying it to the user. If the scene is not already in the stack, we push it to the top. Jumping is useful for applications that frequently switch between a number of scenes. Jumping is also optimized to be faster than doing the same via push and pop. Note that to jump correctly, each scene requires a *scene key*. The scene key identifies the scene, enabling Viro to recognize when said scene is already on the stack so we can quickly jump to it. [block:code] { "codes": [ { "code": "var SecondScene = require('./SecondScene');\n\nvar FirstScene = React.createClass({\n render: function() {\n return (\n <ViroScene>\n <ViroImage source={require('./res/image.jpg')} \n position={[0, 0, -5]} \n onClick={this._jumpNextScene}/> \n </ViroScene>\n );\n },\n \n _jumpNextScene(){\n this.props.sceneNavigator.jump(\"scene2\", {scene:SecondScene});\n },\n});\n\nmodule.exports = FirstScene;", "language": "javascript" } ] } [/block] [block:api-header] { "title": "Replacing" } [/block] Finally, to simply replace the scene at the top of the stack with a different scene, use the ```replace``` method. Replace is useful for applications that have no need for a hierarchical scene stack, and instead simply swap out one scene for another at the root level. [block:code] { "codes": [ { "code": "var SecondScene = require('./SecondScene');\n\nvar FirstScene = React.createClass({\n render: function() {\n return (\n <ViroScene>\n <ViroImage source={require('./res/image.jpg')} \n position={[0, 0, -5]} \n onClick={this._replaceNextScene}/> \n </ViroScene>\n );\n },\n \n _replaceNextScene(){\n this.props.sceneNavigator.replace({scene:SecondScene});\n },\n});\n\nmodule.exports = FirstScene;", "language": "javascript" } ] } [/block] [block:api-header] { "title": "Passing Props from Scene to Scene" } [/block] As with most mobile apps, you may also need to pass information through different experiences, or scenes. For example, if a user selects an item from a virtual menu to be then displayed in a newly pushed scene, your application may need to propagate additional information related to the selected item into the new scene. In Viro, there are 3 ways that you can pass information through scenes. **Option 1: Using passProps** If you are looking to pass static properties to your next scene, you can use the *passProps* parameter within the scene navigator. This approach is great for providing individual scenes with static, unchanging parameters - the passProp **cannot be changed** once you push a scene with that prop! (To get around that you can use option #2 below.) [block:code] { "codes": [ { "code": "// For your initial scene, you can populate passProps as part of \n// the initialScene dictionary, using the following syntax:\n<ViroARSceneNavigator \n apiKey=\"API_KEY_HERE\"\n initialScene={{\n scene:InitialARScene, \n \t\t\t\t\t\tpassProps:{displayObject:true}\n }}/>\n\n// To Pass properties when pushing another scene, use the following syntax:\nthis.props.sceneNavigator.jump(\"Shop\", {\n scene : require('./Shop'),\n passProps: {\n displayObject : true\n }\n);", "language": "javascript" } ] } [/block] Then in our InitialARScene, you should be able to reference your value with **this.props.displayObject.** **Option 2: Using viroAppProps** The scene navigator object is actually passed as a prop to each scene that you have. If you are using ViroSceneNavigator the prop is called **sceneNavigator**. If you are using ViroARSceneNavigator it's called **arSceneNavigator**. The navigators have a dictionary object called **viroAppProps** which you can use as global dictionary to store and pass values across your app. This can be used to maintain application state. [block:code] { "codes": [ { "code": "// For your initial scene, you treat viroAppProps as a \n// global dictionary container with which to pass information.\n<ViroARSceneNavigator \n apiKey=\"API_KEY_HERE\"\n initialScene={{scene:InitialARScene}}\n viroAppProps={{displayObject:false}}\n />\n\n// To pass information from the current scene to the next, simply\n// reference the dictionary with the sceneNavigator that is passed\n// to each scene.\nthis.props.sceneNavigator.viroAppProps={displayObject:true}; ", "language": "javascript" } ] } [/block] Then in our InitialARScene, you should be able to check your value with **this.props.sceneNavigator.viroAppProps.displayObject.** **Option 3: Using Redux** Generally, if you want props to span across multiple components I recommend using Redux to manage application state. This would mostly be the case for more involved and larger applications, where the above two solutions would not be sufficient, and most likely get out of hand pretty quickly the larger your application grows. More info here on Redux: https://medium.com/@jonlebensold/getting-started-with-react-native-redux-2b01408c0053