Conversation
* De-emphasise Overte being just a VR platform * Don't use var in example scripts
* Convert from markdown to reStructuredText format * Fix syntax error in example code * Expand Equip Item section with full working example * Add "use strict" and remove vars in example code
* console.log in an exported function will not show in logs
* "use strict", etc. * Also add a way for desktop users to try out the avatar script by pressing "x" on their keyboard.
* Remove section on using Package Model to add scripts; does not work * Replace image of text editor with code block, including highlighted line
* Encourage use of server entity script in some situations * Correct steps to add a client entity script, with scripts page icon. * Example script now wil "use strict", etc.
* Correct steps to attach a Server Entity Script to an Entity * Example script will now "use strict", etc.
* I don't mean to alarm anyone, but it is now closer to 40 years since the 80s. A slight change to the wording to make this tutorial timeless.
* Loading a script from the UI will load it persistently
* clickDownOnEntity only responds to mouse click events; cannot be used in VR with controllers * mousePressOnEntity responds to both mouse click and controller trigger events
|
|
||
| 1. Open your 'Domain Administration Panel'. If you are on a local sandbox, open it by clicking on the Overte icon in the taskbar notifications and 'click Settings'. | ||
| 2. From the menu, go to **Content > Scripts**. | ||
| 3. In the Persistent Scripts section, click **+** and paste the URL to your script under 'Script URL'. |
There was a problem hiding this comment.
I assume these are the same as the assignment client script under http://localhost:40100/assignment ?
If you think so too, maybe we should open an issue about streamlining the UI there. It is quite confusing to have more or less the same thing in two different places.
| (function(){ | ||
| "use strict" | ||
| let triggerDistance = 0.0; | ||
| const TRIGGER_THRESHOLD = 0.9; | ||
| const LOAD_THRESHOLD = 0.6 | ||
| const rightHandIndex = MyAvatar.getJointIndex("RightHand"); | ||
| const rightArmIndex = MyAvatar.getJointIndex("RightArm"); | ||
| let triggered = false; | ||
|
|
||
| function fireBall(position, speed) { | ||
| const baseID = Entities.addEntity({ | ||
| type: "Sphere", | ||
| color: { blue: 128, green: 128, red: 20 }, | ||
| dimensions: { x: 0.1, y: 0.1, z: 0.1 }, | ||
| position: position, | ||
| dynamic: true, | ||
| collisionless: false, | ||
| lifetime: 10, // Thrown fireball will despawn after 10 seconds | ||
| gravity: speed, | ||
| userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }" | ||
| }); | ||
| Entities.editEntity(baseID, { velocity: speed }); | ||
| } | ||
|
|
||
| // VR users can push their right hand forwards from their shoulder to throw | ||
| Script.update.connect(function() { | ||
| const rightHandPos = MyAvatar.getJointPosition(rightHandIndex); | ||
| const rightArmPos = MyAvatar.getJointPosition(rightArmIndex); | ||
| const fireDir = Vec3.subtract(rightHandPos, rightArmPos); | ||
| const distance = Vec3.length(fireDir); | ||
| triggerDistance = distance > triggerDistance ? distance : triggerDistance; | ||
| if (!triggered) { | ||
| if (distance < LOAD_THRESHOLD * triggerDistance) { | ||
| triggered = true; | ||
| } | ||
| } else if (distance > TRIGGER_THRESHOLD * triggerDistance) { | ||
| triggered = false; | ||
| fireBall(rightHandPos, Vec3.normalize(fireDir)); | ||
| } | ||
| }); | ||
| MyAvatar.scaleChanged.connect(function () { | ||
| triggerDistance = 0.0; | ||
| }); | ||
|
|
||
| // Desktop users can press and release "x" to throw | ||
| function keyReleaseEvent(event) { | ||
| if ((event.text.toUpperCase() === "X") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) { | ||
| const rightHandPos = MyAvatar.getJointPosition(rightHandIndex); | ||
| const rightArmPos = MyAvatar.getJointPosition(rightArmIndex); | ||
| const fireDir = getPointingDirection(); | ||
| fireBall(rightHandPos, Vec3.normalize(fireDir)); | ||
| } | ||
| } | ||
| // Runs desktop function whenever (any) key is released | ||
| Controller.keyReleaseEvent.connect(keyReleaseEvent); | ||
| // It is a good idea to clean up when the script stops | ||
| Script.scriptEnding.connect(function () { | ||
| print("removing key mapping"); | ||
| Controller.keyReleaseEvent.disconnect(keyReleaseEvent); | ||
| }); | ||
| }()); |
There was a problem hiding this comment.
| (function(){ | |
| "use strict" | |
| let triggerDistance = 0.0; | |
| const TRIGGER_THRESHOLD = 0.9; | |
| const LOAD_THRESHOLD = 0.6 | |
| const rightHandIndex = MyAvatar.getJointIndex("RightHand"); | |
| const rightArmIndex = MyAvatar.getJointIndex("RightArm"); | |
| let triggered = false; | |
| function fireBall(position, speed) { | |
| const baseID = Entities.addEntity({ | |
| type: "Sphere", | |
| color: { blue: 128, green: 128, red: 20 }, | |
| dimensions: { x: 0.1, y: 0.1, z: 0.1 }, | |
| position: position, | |
| dynamic: true, | |
| collisionless: false, | |
| lifetime: 10, // Thrown fireball will despawn after 10 seconds | |
| gravity: speed, | |
| userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }" | |
| }); | |
| Entities.editEntity(baseID, { velocity: speed }); | |
| } | |
| // VR users can push their right hand forwards from their shoulder to throw | |
| Script.update.connect(function() { | |
| const rightHandPos = MyAvatar.getJointPosition(rightHandIndex); | |
| const rightArmPos = MyAvatar.getJointPosition(rightArmIndex); | |
| const fireDir = Vec3.subtract(rightHandPos, rightArmPos); | |
| const distance = Vec3.length(fireDir); | |
| triggerDistance = distance > triggerDistance ? distance : triggerDistance; | |
| if (!triggered) { | |
| if (distance < LOAD_THRESHOLD * triggerDistance) { | |
| triggered = true; | |
| } | |
| } else if (distance > TRIGGER_THRESHOLD * triggerDistance) { | |
| triggered = false; | |
| fireBall(rightHandPos, Vec3.normalize(fireDir)); | |
| } | |
| }); | |
| MyAvatar.scaleChanged.connect(function () { | |
| triggerDistance = 0.0; | |
| }); | |
| // Desktop users can press and release "x" to throw | |
| function keyReleaseEvent(event) { | |
| if ((event.text.toUpperCase() === "X") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) { | |
| const rightHandPos = MyAvatar.getJointPosition(rightHandIndex); | |
| const rightArmPos = MyAvatar.getJointPosition(rightArmIndex); | |
| const fireDir = getPointingDirection(); | |
| fireBall(rightHandPos, Vec3.normalize(fireDir)); | |
| } | |
| } | |
| // Runs desktop function whenever (any) key is released | |
| Controller.keyReleaseEvent.connect(keyReleaseEvent); | |
| // It is a good idea to clean up when the script stops | |
| Script.scriptEnding.connect(function () { | |
| print("removing key mapping"); | |
| Controller.keyReleaseEvent.disconnect(keyReleaseEvent); | |
| }); | |
| }()); | |
| (function(){ | |
| "use strict" | |
| let triggerDistance = 0.0; | |
| const TRIGGER_THRESHOLD = 0.9; | |
| const LOAD_THRESHOLD = 0.6 | |
| const rightHandIndex = MyAvatar.getJointIndex("RightHand"); | |
| const rightArmIndex = MyAvatar.getJointIndex("RightArm"); | |
| let triggered = false; | |
| function fireBall(position, speed) { | |
| const baseID = Entities.addEntity({ | |
| type: "Sphere", | |
| color: { blue: 128, green: 128, red: 20 }, | |
| dimensions: { x: 0.1, y: 0.1, z: 0.1 }, | |
| position: position, | |
| dynamic: true, | |
| collisionless: false, | |
| lifetime: 10, // Thrown fireball will despawn after 10 seconds | |
| gravity: speed, | |
| userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }" | |
| }); | |
| Entities.editEntity(baseID, { velocity: speed }); | |
| } | |
| // VR users can push their right hand forwards from their shoulder to throw | |
| Script.update.connect(function() { | |
| const rightHandPos = MyAvatar.getJointPosition(rightHandIndex); | |
| const rightArmPos = MyAvatar.getJointPosition(rightArmIndex); | |
| const fireDir = Vec3.subtract(rightHandPos, rightArmPos); | |
| const distance = Vec3.length(fireDir); | |
| triggerDistance = distance > triggerDistance ? distance : triggerDistance; | |
| if (!triggered) { | |
| if (distance < LOAD_THRESHOLD * triggerDistance) { | |
| triggered = true; | |
| } | |
| } else if (distance > TRIGGER_THRESHOLD * triggerDistance) { | |
| triggered = false; | |
| fireBall(rightHandPos, Vec3.normalize(fireDir)); | |
| } | |
| }); | |
| MyAvatar.scaleChanged.connect(function () { | |
| triggerDistance = 0.0; | |
| }); | |
| // Desktop users can press and release "x" to throw | |
| function keyReleaseEvent(event) { | |
| if ((event.text.toUpperCase() === "X") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) { | |
| const rightHandPos = MyAvatar.getJointPosition(rightHandIndex); | |
| const rightArmPos = MyAvatar.getJointPosition(rightArmIndex); | |
| const fireDir = getPointingDirection(); | |
| fireBall(rightHandPos, Vec3.normalize(fireDir)); | |
| } | |
| } | |
| // Runs desktop function whenever (any) key is released | |
| Controller.keyReleaseEvent.connect(keyReleaseEvent); | |
| // It is a good idea to clean up when the script stops | |
| Script.scriptEnding.connect(function () { | |
| print("removing key mapping"); | |
| Controller.keyReleaseEvent.disconnect(keyReleaseEvent); | |
| }); | |
| }()); |
The indentation of the code-block directive is 3 spaces, so by adding 4 spaces, the resulting code-block has everything indented one space too far. You can change the indentation of the directive to 4 spaces, to avoid having to use 3 spaces in the first indentation instead. (See my other comment/suggestion.)
| .. code-block:: javascript | ||
| :caption: throw_ball.js |
There was a problem hiding this comment.
| .. code-block:: javascript | |
| :caption: throw_ball.js | |
| .. code-block:: javascript | |
| :caption: throw_ball.js |
If you prefer having 4-space indentation for the directive, instead of having the first indentation of the script be 3 spaces.
| Server Entity Scripts | ||
| ##################### | ||
|
|
||
| You can make content in Overte interactive by attaching scripts to entities. *Server entity scripts* are entity scripts that run on the server (or domain) that hosts the entity. These scripts run persistently in a domain, even if there are no users present. This means that there is only one instance of the script is running at a time, and it is running on the server. Any behavior that is controlled by your script will be seen and heard by everyone in the domain. |
There was a problem hiding this comment.
| You can make content in Overte interactive by attaching scripts to entities. *Server entity scripts* are entity scripts that run on the server (or domain) that hosts the entity. These scripts run persistently in a domain, even if there are no users present. This means that there is only one instance of the script is running at a time, and it is running on the server. Any behavior that is controlled by your script will be seen and heard by everyone in the domain. | |
| You can make content in Overte interactive by attaching scripts to entities. *Server entity scripts* are entity scripts that run on the server (or domain) that hosts the entity. These scripts run persistently in a domain, even if there are no users present. This means that there is only one instance of the script running at a time, and it is running on the server. Any behavior that is controlled by your script will be seen or heard by everyone in the domain. |
|
|
||
| .. note:: An entity can have multiple server entity scripts attached to it, but all of these must be through a single file URL. | ||
|
|
||
| .. |scripts-icon| image:: _images/create-properties-scripts-icon.png |
| 3. In the **Create** app, go to the 'Properties' tab and select the Scripts icon. |scripts-icon| | ||
| 4. For 'Server Script', enter the URL to your server entity script. | ||
|
|
||
| .. note:: An entity can have multiple server entity scripts attached to it, but all of these must be through a single file URL. |
There was a problem hiding this comment.
Does this apply to client scripts as well? I had no idea we could do this, and thought this is what we added Script Entities for.
| @@ -0,0 +1,76 @@ | |||
| ##################### | |||
| Server Entity Scripts | |||
| ##################### | |||
There was a problem hiding this comment.
This page should probably mention the Developer → Scripting → Entity Script Server Log.
|
|
||
| <div class="admonition note"> | ||
| <p class="admonition-title">Note</p> | ||
| <p>Entity scripts, unlike interface scripts, are in containing functions. The example scripts here cannot be attached to an entity (and be used as an entity script) unless they are in a containing function ``function() {}``.</p> |
There was a problem hiding this comment.
| <p>Entity scripts, unlike interface scripts, are in containing functions. The example scripts here cannot be attached to an entity (and be used as an entity script) unless they are in a containing function <code>function() {}</code>.</p> |
|
You can apply multiple suggestions at once from the Files changed page. |
Co-authored-by: Julian Groß <julian.g@posteo.de>
This PR brings the Script section of the docs up to date.