Fixes for issues found with last Pull Request

1)  Does not give the message regarding not having permissions except for when first rezing the tool.
▶ Fixed - Added in a check for every time there is a collision between the parent-ator and another entity

2) Sound almost unhearable due to distortion
▶ Fixed -  Changed audio to 16 bit mono

3) The Parent-ator model rezzes pointing at the user's face. Would probably be better to add 180 to START_POSITION.y then normalize.
▶ Fixed - Added 180 to START_ROTATION (instead fo START_POSITION) and normalized

4) The Parent-ator model floats away. Would suggest increasing linear damping from the default. Maybe go to 0.9 or more.
▶ Fixed - Added damping of 0.9

5) The face normals are inverted on the three rings surrounding the barrel of the Parent-ator model.
▶ Fixed - Normals flipped

6) Also if the user taps an object then releases and re-equips with the Parent-ator it continues to display "tap the child" but will set the object tapped first as the child of the first other object tapped after re-equipping. So the messages change from Tap the child to the "Yay" success message.
▶ Fixed - Re-equiping now resets the parent-ator.

7) Parenting can be broken with this. On occasions the Parentator seems to get out of sequence. With a group of objects eventually one or more can get orphaned. In effect (occasionally ) a single first tap can produce the success message.
▶ Believed to be fixed - I was unable to really reproduce the problem but the fix for the previous item should fix this too, I believe.

8) There is an error in the description on line 7 of parentator.js
▶ Fixed - Changed reference to pingpong gun to parent-ator

9) Equipping can fail with a smaller than normal avatar as the offsets are hard coded rather than scaled relative to the user's scale.
▶ Fixed - I realized I was adding the entity with larger dimensions than the model normally had. I've scaled it down to where it should be and I think this has solved the issue.
This commit is contained in:
VRCat\VRKitten 2017-07-26 12:14:59 -06:00
parent a1f2e786af
commit 635be3e2e9
8 changed files with 119 additions and 17397 deletions

View file

@ -9,17 +9,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
var scriptURL = Script.resolvePath('parentator.js'); var scriptURL = Script.resolvePath('parentator.js');
var MODEL_URL = Script.resolvePath('resources/Parent-Tool-Production.fbx'); var MODEL_URL = Script.resolvePath('resources/Parent-Tool-Production.fbx');
var COLLISION_HULL_URL = Script.resolvePath('resources/Parent-Tool-CollisionHull.obj'); var COLLISION_HULL_URL = Script.resolvePath('resources/Parent-Tool-CollisionHull.obj');
//var COLLISION_SOUND_URL = 'http://hifi-production.s3.amazonaws.com/DomainContent/Toybox/ping_pong_gun/plastic_impact.L.wav';
var START_POSITION = Vec3.sum(Vec3.sum(MyAvatar.position, { // the fbx model needs to be rotated from where it would naturally face when it first initializes
x: 0, var ROT_Y_180 = {x: 0, y: 1, z: 0, w: 0};
y: 0.5, var START_ROTATION = Quat.normalize(Quat.multiply(ROT_Y_180, Camera.getOrientation()));
z: 0 var START_POSITION = Vec3.sum(Vec3.sum(MyAvatar.position, { x: 0, y: 0.5, z: 0 }), Vec3.multiply(0.7, Quat.getForward(Camera.getOrientation())));
}), Vec3.multiply(0.7, Quat.getForward(Camera.getOrientation())));
var START_ROTATION = Vec3.sum(MyAvatar.position, Vec3.multiply(1.5, Quat.getFront(Camera.getOrientation())));
var parentator = Entities.addEntity({ var parentator = Entities.addEntity({
@ -29,15 +27,14 @@ var parentator = Entities.addEntity({
shapeType: 'compound', shapeType: 'compound',
compoundShapeURL: COLLISION_HULL_URL, compoundShapeURL: COLLISION_HULL_URL,
dynamic: true, dynamic: true,
damping: 0.9,
script: scriptURL, script: scriptURL,
dimensions: { dimensions: {
x: 0.125, x: 0.1270,
y: 0.2875, y: 0.2715,
z: 0.5931 z: 0.4672
}, },
position: START_POSITION, position: START_POSITION,
rotation: START_ROTATION, rotation: START_ROTATION,
@ -45,15 +42,15 @@ var parentator = Entities.addEntity({
"grabbableKey": {"grabbable": true}, "grabbableKey": {"grabbable": true},
"equipHotspots": [ "equipHotspots": [
{ {
"position": {"x": 0.0, "y": 0.0, "z": 0.0}, "position": {"x": 0.0, "y": 0.0, "z": -0.170 },
"radius": 0.3, "radius": 0.15,
"joints":{ "joints":{
"RightHand":[ "RightHand":[
{"x":0.05, "y":0.3, "z":0.03}, {"x":0.05, "y":0.25, "z":0.03},
{"x":-0.5, "y":-0.5, "z":-0.5, "w":0.5} {"x":-0.5, "y":-0.5, "z":-0.5, "w":0.5}
], ],
"LeftHand":[ "LeftHand":[
{"x":-0.05, "y":0.3, "z":0.03}, {"x":-0.05, "y":0.25, "z":0.03},
{"x":-0.5, "y":0.5, "z":0.5, "w":0.5} {"x":-0.5, "y":0.5, "z":0.5, "w":0.5}
] ]
} }
@ -63,8 +60,7 @@ var parentator = Entities.addEntity({
}); });
function cleanUp() { function cleanUp() {
Entities.deleteEntity(parentator); Entities.deleteEntity(parentator);
} }
Script.scriptEnding.connect(cleanUp); Script.scriptEnding.connect(cleanUp);

View file

@ -4,63 +4,85 @@
// Created by Jeff Moyes on 6/30/2017 // Created by Jeff Moyes on 6/30/2017
// Copyright 2017 High Fidelity, Inc. // Copyright 2017 High Fidelity, Inc.
// //
// This script shoots a ping pong ball. // This script allows users to parent one object to another via the "parent-ator" entity
// (which looks like a purple gun-like object). The user:
// 1) equips their avatar with this parent-ator,
// 2) taps the end of the parent-ator on an entity (which becomes the child entity), and
// 3) taps the end of the parent-ator on a second entity (which becomes the parent entity)
//
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
(function() { (function() {
var MESSAGE_1_TEXTURE_URL = Script.resolvePath( 'resources/message-1-start.png' );
var MESSAGE_2_TEXTURE_URL = Script.resolvePath( 'resources/message-2-noperms.png' );
var MESSAGE_3_TEXTURE_URL = Script.resolvePath( 'resources/message-3-tryagain.png' );
var MESSAGE_4_TEXTURE_URL = Script.resolvePath( 'resources/message-4-setparent.png' );
var MESSAGE_5_TEXTURE_URL = Script.resolvePath( 'resources/message-5-success.png' );
var MESSAGE_1_TEXTURE_URL = Script.resolvePath('resources/message-1-start.png'); var SOUND_1_URL = Script.resolvePath( 'resources/parent-tool-sound1.wav' );
var MESSAGE_2_TEXTURE_URL = Script.resolvePath('resources/message-2-noperms.png'); var SOUND_2_URL = Script.resolvePath( 'resources/parent-tool-sound2.wav' );
var MESSAGE_3_TEXTURE_URL = Script.resolvePath('resources/message-3-tryagain.png'); var SOUND_ERROR_URL = Script.resolvePath( 'resources/parent-tool-sound-error.wav' );
var MESSAGE_4_TEXTURE_URL = Script.resolvePath('resources/message-4-setparent.png'); var SOUND_SUCCESS_URL = Script.resolvePath( 'resources/parent-tool-sound-success.wav' );
var MESSAGE_5_TEXTURE_URL = Script.resolvePath('resources/message-5-success.png');
var SOUND_1_URL = Script.resolvePath('resources/parent-tool-sound1.wav');
var SOUND_2_URL = Script.resolvePath('resources/parent-tool-sound2.wav');
var SOUND_ERROR_URL = Script.resolvePath('resources/parent-tool-sound-error.wav');
var SOUND_SUCCESS_URL = Script.resolvePath('resources/parent-tool-sound-success.wav');
var SOUND_1, SOUND_2, SOUND_ERROR, SOUND_SUCCESS; var SOUND_1, SOUND_2, SOUND_ERROR, SOUND_SUCCESS;
var childEntityID, parentEntityID;
var childEntityID = 0;
var parentEntityID = 0;
function Parentator() { function Parentator() {
return; return;
} }
Parentator.prototype.preload = function(entityID) { Parentator.prototype.reset = function() {
this.entityID = entityID; childEntityID = 0;
SOUND_1 = SoundCache.getSound(SOUND_1_URL); parentEntityID = 0;
SOUND_2 = SoundCache.getSound(SOUND_2_URL);
SOUND_ERROR = SoundCache.getSound(SOUND_ERROR_URL);
SOUND_SUCCESS = SoundCache.getSound(SOUND_SUCCESS_URL);
};
Parentator.prototype.startEquip = function(entityID, args) {
if (Entities.canRez()) { if (Entities.canRez()) {
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "message-1-start.png.001": MESSAGE_1_TEXTURE_URL }) }); Entities.editEntity( this.entityID, { textures: JSON.stringify({ "texture-message": MESSAGE_1_TEXTURE_URL }) });
this.playSoundAtCurrentPosition(SOUND_1); this.playSoundAtCurrentPosition( SOUND_1 );
} else { } else {
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "message-1-start.png.001": MESSAGE_2_TEXTURE_URL }) }); Entities.editEntity( this.entityID, { textures: JSON.stringify({ "texture-message": MESSAGE_2_TEXTURE_URL }) });
this.playSoundAtCurrentPosition(SOUND_ERROR); this.playSoundAtCurrentPosition( SOUND_ERROR );
} }
}; }
Parentator.prototype.collisionWithEntity = function(parentatorID, collidedID, collisionInfo) { Parentator.prototype.preload = function( entityID ) {
this.entityID = entityID;
SOUND_1 = SoundCache.getSound( SOUND_1_URL );
SOUND_2 = SoundCache.getSound( SOUND_2_URL );
SOUND_ERROR = SoundCache.getSound( SOUND_ERROR_URL );
SOUND_SUCCESS = SoundCache.getSound( SOUND_SUCCESS_URL );
// The following is in case a user has been in a domain where they didn't have permission to rez
// (and that is displayed on the parent-tor screen) and then they move to a domain where they can rez
Window.domainChanged.connect( function() {
this.reset();
});
}
Parentator.prototype.startEquip = function( args ) {
this.hand = args[0];
this.reset();
}
Parentator.prototype.collisionWithEntity = function( parentatorID, collidedID, collisionInfo ) {
// We don't want to be able to select Lights, Zone, and Particles but they are not collidable anyway so we don't have to worry about them // We don't want to be able to select Lights, Zone, and Particles but they are not collidable anyway so we don't have to worry about them
var collidedEntityProperties = Entities.getEntityProperties(collidedID); var collidedEntityProperties = Entities.getEntityProperties( collidedID );
if ( !Entities.canRez() ) {
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "texture-message": MESSAGE_2_TEXTURE_URL }) });
this.playSoundAtCurrentPosition( SOUND_ERROR );
}
// User has just reclicked the first entity (or it's 'bounced') // User has just reclicked the first entity (or it's 'bounced')
if ( childEntityID == collidedID ) { if ( childEntityID == collidedID ) {
return; return;
} }
if (collidedEntityProperties.locked) { if ( collidedEntityProperties.locked ) {
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "message-1-start.png.001": MESSAGE_3_TEXTURE_URL }) }); Entities.editEntity( this.entityID, { textures: JSON.stringify({ "texture-message": MESSAGE_3_TEXTURE_URL }) });
this.playSoundAtCurrentPosition(SOUND_ERROR); this.playSoundAtCurrentPosition( SOUND_ERROR );
return; return;
} }
@ -69,46 +91,43 @@
childEntityID = collidedID; childEntityID = collidedID;
// if there is a parentID, remove it // if there is a parentID, remove it
if (collidedEntityProperties.parentID != "{00000000-0000-0000-0000-000000000000}") { if ( collidedEntityProperties.parentID != "{00000000-0000-0000-0000-000000000000}" ) {
Entities.editEntity( collidedID, { parentID: "{00000000-0000-0000-0000-000000000000}" }); Entities.editEntity( collidedID, { parentID: "{00000000-0000-0000-0000-000000000000}" });
} }
if (collidedEntityProperties.dynamic) { if ( collidedEntityProperties.dynamic ) {
Entities.editEntity( collidedID, { dynamic: false }); Entities.editEntity( collidedID, { dynamic: false });
} }
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "message-1-start.png.001": MESSAGE_4_TEXTURE_URL }) }); Entities.editEntity( this.entityID, { textures: JSON.stringify({ "texture-message": MESSAGE_4_TEXTURE_URL }) });
this.playSoundAtCurrentPosition(SOUND_2); this.playSoundAtCurrentPosition( SOUND_2 );
} else { } else {
parentEntityID = collidedID; parentEntityID = collidedID;
this.setParent(); this.setParent();
} }
}; }
Parentator.prototype.setParent = function() { Parentator.prototype.setParent = function() {
Entities.editEntity(childEntityID, { parentID: parentEntityID }); Entities.editEntity( childEntityID, { parentID: parentEntityID });
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "message-1-start.png.001": MESSAGE_5_TEXTURE_URL }) }); Entities.editEntity( this.entityID, { textures: JSON.stringify({ "texture-message": MESSAGE_5_TEXTURE_URL }) });
this.playSoundAtCurrentPosition( SOUND_SUCCESS );
Script.setTimeout(function() { Script.setTimeout( function() {
childEntityID = 0; this.reset()
parentEntityID = 0; }.bind( this ), 5000 );
Entities.editEntity( this.entityID, { textures: JSON.stringify({ "message-1-start.png.001": MESSAGE_1_TEXTURE_URL }) }); }
this.playSoundAtCurrentPosition(SOUND_SUCCESS);
}.bind(this), 5000);
};
Parentator.prototype.playSoundAtCurrentPosition = function(sound) { Parentator.prototype.playSoundAtCurrentPosition = function( sound ) {
var audioProperties = { var audioProperties = {
volume: 0.3, volume: 0.3,
position: Entities.getEntityProperties(this.entityID).position position: Entities.getEntityProperties( this.entityID ).position
} }
Audio.playSound(sound, audioProperties); Audio.playSound( sound, audioProperties );
}; }
Parentator.prototype.unload = function () { Parentator.prototype.unload = function () {
Entities.deleteEntity(this.entityID); Entities.deleteEntity( this.entityID );
}; }
// entity scripts always need to return a newly constructed object of our type // entity scripts always need to return a newly constructed object of our type
return new Parentator(); return new Parentator();