mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 15:49:24 +02:00
Fixed up blocks scripts
This commit is contained in:
parent
ea3f7f0274
commit
fe19b5511c
2 changed files with 193 additions and 126 deletions
|
@ -1,115 +1,133 @@
|
||||||
(function(){
|
//
|
||||||
|
// magneticBlock.js
|
||||||
|
//
|
||||||
|
// Created by Matti Lahtinen 4/3/2017
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
// Makes the entity the script is bound to connect to nearby, similarly sized entities, like a magnet.
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const SNAPSOUND_SOURCE = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs"));
|
||||||
|
// Preload trick for faster playback
|
||||||
|
const RANGE_MULTIPLER = 1.5;
|
||||||
|
|
||||||
const SNAPSOUND = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs"));
|
// Helper for detecting nearby objects
|
||||||
const RANGE_MULTIPLER = 1.5;
|
function findEntitiesInRange(releasedProperties) {
|
||||||
|
var dimensions = releasedProperties.dimensions;
|
||||||
// Helper for detecting nearby objects
|
return Entities.findEntities(releasedProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER);
|
||||||
function findEntitiesInRange(releasedProperties) {
|
|
||||||
var dimensions = releasedProperties.dimensions;
|
|
||||||
return Entities.findEntities(releasedProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNearestValidEntityProperties(releasedProperties) {
|
|
||||||
var entities = findEntitiesInRange(releasedProperties);
|
|
||||||
var nearestEntity = null;
|
|
||||||
var nearest = 9999999999999;
|
|
||||||
var releaseSize = Vec3.length(releasedProperties.dimensions);
|
|
||||||
entities.forEach(function(entityId) {
|
|
||||||
if(entityId !== releasedProperties.id) {
|
|
||||||
var entity = Entities.getEntityProperties(entityId, ['position', 'rotation', 'dimensions']);
|
|
||||||
var distance = Vec3.distance(releasedProperties.position, entity.position);
|
|
||||||
var scale = releaseSize/Vec3.length(entity.dimensions);
|
|
||||||
|
|
||||||
if (distance < nearest && (scale >= 0.5 && scale <= 2)) {
|
|
||||||
nearestEntity = entity;
|
|
||||||
nearest = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return nearestEntity;
|
|
||||||
}
|
|
||||||
// Create the 'class'
|
|
||||||
function MagneticBlock () { }
|
|
||||||
// Bind pre-emptive events
|
|
||||||
MagneticBlock.prototype = {
|
|
||||||
// When script is bound to an entity, preload is the first callback called with the entityID. It will behave as the constructor
|
|
||||||
preload: function (id) {
|
|
||||||
/*
|
|
||||||
We will now override any existing userdata with the grabbable property.
|
|
||||||
Only retrieving userData
|
|
||||||
*/
|
|
||||||
var val = Entities.getEntityProperties(id, ['userData'])
|
|
||||||
var userData = {};
|
|
||||||
if (val.userData && val.userData.length > 0 ) {
|
|
||||||
try {
|
|
||||||
userData = JSON.parse(val.userData);
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
// Object must be triggerable inorder to bind events.
|
|
||||||
userData.grabbableKey = {grabbable: true};
|
|
||||||
// Apply the new properties to entity of id
|
|
||||||
Entities.editEntity(id, {userData: JSON.stringify(userData)});
|
|
||||||
this.held = false;
|
|
||||||
|
|
||||||
// We will now create a custom binding, to keep the 'current' context as these are callbacks called without context
|
|
||||||
var t = this;
|
|
||||||
this.callbacks = {};
|
|
||||||
this.callbacks["releaseGrab"] = function () {
|
|
||||||
var released = Entities.getEntityProperties(id,["position", "rotation", "dimensions"]);
|
|
||||||
var target = getNearestValidEntityProperties(released);
|
|
||||||
if (target !== null) {
|
|
||||||
// We found nearest, now lets do the snap calculations
|
|
||||||
// Plays the snap sound between the two objects.
|
|
||||||
Audio.playSound(SNAPSOUND, {
|
|
||||||
volume: 1,
|
|
||||||
position: Vec3.mix(target.position, released.position, 0.5)
|
|
||||||
});
|
|
||||||
// Check Nearest Axis
|
|
||||||
var difference = Vec3.subtract(released.position, target.position);
|
|
||||||
var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference);
|
|
||||||
|
|
||||||
var abs = {
|
|
||||||
x: Math.abs(relativeDifference.x),
|
|
||||||
y: Math.abs(relativeDifference.y),
|
|
||||||
z: Math.abs(relativeDifference.z)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (abs.x >= abs.y && abs.x >= abs.z) {
|
|
||||||
relativeDifference.y = 0;
|
|
||||||
relativeDifference.z = 0;
|
|
||||||
if (relativeDifference.x > 0) {
|
|
||||||
relativeDifference.x = target.dimensions.x / 2 + released.dimensions.x / 2;
|
|
||||||
} else {
|
|
||||||
relativeDifference.x = -target.dimensions.x / 2 - released.dimensions.x / 2;
|
|
||||||
}
|
|
||||||
} else if (abs.y >= abs.x && abs.y >= abs.z) {
|
|
||||||
relativeDifference.x = 0;
|
|
||||||
relativeDifference.z = 0;
|
|
||||||
if (relativeDifference.y > 0) {
|
|
||||||
relativeDifference.y = target.dimensions.y / 2 + released.dimensions.y / 2;
|
|
||||||
} else {
|
|
||||||
relativeDifference.y = -target.dimensions.y / 2 - released.dimensions.y / 2;
|
|
||||||
}
|
|
||||||
} else if (abs.z >= abs.x && abs.z >= abs.y ) {
|
|
||||||
relativeDifference.x = 0;
|
|
||||||
relativeDifference.y = 0;
|
|
||||||
if (relativeDifference.z > 0) {
|
|
||||||
relativeDifference.z = target.dimensions.z / 2 + released.dimensions.z / 2;
|
|
||||||
} else {
|
|
||||||
relativeDifference.z = -target.dimensions.z / 2 - released.dimensions.z / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var newPosition = Vec3.multiplyQbyV(target.rotation, relativeDifference);
|
|
||||||
Entities.editEntity(id, {rotation: target.rotation, position: Vec3.sum(target.position, newPosition)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.releaseGrab = this.callbacks["releaseGrab"];
|
|
||||||
Script.scriptEnding.connect( function () {
|
|
||||||
Script.removeEventHandler(id, "releaseGrab", this.callbacks["releaseGrab"]); //continueNearGrab
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return new MagneticBlock();
|
function getNearestValidEntityProperties(releasedProperties) {
|
||||||
|
var entities = findEntitiesInRange(releasedProperties);
|
||||||
|
var nearestEntity = null;
|
||||||
|
var nearest = 9999999999999;
|
||||||
|
var releaseSize = Vec3.length(releasedProperties.dimensions);
|
||||||
|
entities.forEach(function(entityId) {
|
||||||
|
if (entityId !== releasedProperties.id) {
|
||||||
|
var entity = Entities.getEntityProperties(entityId, ['position', 'rotation', 'dimensions']);
|
||||||
|
var distance = Vec3.distance(releasedProperties.position, entity.position);
|
||||||
|
var scale = releaseSize / Vec3.length(entity.dimensions);
|
||||||
|
|
||||||
|
if (distance < nearest && (scale >= 0.5 && scale <= 2)) {
|
||||||
|
nearestEntity = entity;
|
||||||
|
nearest = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return nearestEntity;
|
||||||
|
}
|
||||||
|
// Create the 'class'
|
||||||
|
function MagneticBlock() {}
|
||||||
|
// Bind pre-emptive events
|
||||||
|
MagneticBlock.prototype = {
|
||||||
|
// When script is bound to an entity, preload is the first callback called with the entityID. It will behave as the constructor
|
||||||
|
preload: function(id) {
|
||||||
|
/*
|
||||||
|
We will now override any existing userdata with the grabbable property.
|
||||||
|
Only retrieving userData
|
||||||
|
*/
|
||||||
|
var val = Entities.getEntityProperties(id, ['userData'])
|
||||||
|
var userData = {grabbableKey: {}};
|
||||||
|
|
||||||
|
if (val.userData && val.userData.length > 0) {
|
||||||
|
try {
|
||||||
|
userData = JSON.parse(val.userData);
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Object must be triggerable inorder to bind events.
|
||||||
|
userData.grabbableKey.grabbable = true;
|
||||||
|
|
||||||
|
// Apply the new properties to entity of id
|
||||||
|
Entities.editEntity(id, {
|
||||||
|
userData: JSON.stringify(userData)
|
||||||
|
});
|
||||||
|
this.held = false;
|
||||||
|
// We will now create a custom binding, to keep the 'current' context as these are callbacks called without context
|
||||||
|
var t = this;
|
||||||
|
this.callbacks = {};
|
||||||
|
this.releaseGrab = function() {
|
||||||
|
var released = Entities.getEntityProperties(id, ["position", "rotation", "dimensions"]);
|
||||||
|
var target = getNearestValidEntityProperties(released);
|
||||||
|
if (target !== null) {
|
||||||
|
// We found nearest, now lets do the snap calculations
|
||||||
|
// Plays the snap sound between the two objects.
|
||||||
|
Audio.playSound(SNAPSOUND_SOURCE, {
|
||||||
|
volume: 1,
|
||||||
|
position: Vec3.mix(target.position, released.position, 0.5)
|
||||||
|
});
|
||||||
|
// Check Nearest Axis
|
||||||
|
var difference = Vec3.subtract(released.position, target.position);
|
||||||
|
var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference);
|
||||||
|
|
||||||
|
var abs = {
|
||||||
|
x: Math.abs(relativeDifference.x),
|
||||||
|
y: Math.abs(relativeDifference.y),
|
||||||
|
z: Math.abs(relativeDifference.z)
|
||||||
|
};
|
||||||
|
// Check what value is greater. Simplified.
|
||||||
|
if (abs.x >= abs.y && abs.x >= abs.z) {
|
||||||
|
relativeDifference.y = 0;
|
||||||
|
relativeDifference.z = 0;
|
||||||
|
if (relativeDifference.x > 0) {
|
||||||
|
relativeDifference.x = target.dimensions.x / 2 + released.dimensions.x / 2;
|
||||||
|
} else {
|
||||||
|
relativeDifference.x = -target.dimensions.x / 2 - released.dimensions.x / 2;
|
||||||
|
}
|
||||||
|
} else if (abs.y >= abs.x && abs.y >= abs.z) {
|
||||||
|
relativeDifference.x = 0;
|
||||||
|
relativeDifference.z = 0;
|
||||||
|
if (relativeDifference.y > 0) {
|
||||||
|
relativeDifference.y = target.dimensions.y / 2 + released.dimensions.y / 2;
|
||||||
|
} else {
|
||||||
|
relativeDifference.y = -target.dimensions.y / 2 - released.dimensions.y / 2;
|
||||||
|
}
|
||||||
|
} else if (abs.z >= abs.x && abs.z >= abs.y) {
|
||||||
|
relativeDifference.x = 0;
|
||||||
|
relativeDifference.y = 0;
|
||||||
|
if (relativeDifference.z > 0) {
|
||||||
|
relativeDifference.z = target.dimensions.z / 2 + released.dimensions.z / 2;
|
||||||
|
} else {
|
||||||
|
relativeDifference.z = -target.dimensions.z / 2 - released.dimensions.z / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Can be expanded upon to work in nearest rotation as well, but was not in spec.
|
||||||
|
var newPosition = Vec3.multiplyQbyV(target.rotation, relativeDifference);
|
||||||
|
Entities.editEntity(id, {
|
||||||
|
rotation: target.rotation,
|
||||||
|
position: Vec3.sum(target.position, newPosition)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
Script.removeEventHandler(id, "releaseGrab", this.releaseGrab);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new MagneticBlock();
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,15 +1,64 @@
|
||||||
// Toy
|
//
|
||||||
const MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum.
|
// makeBlocks.js
|
||||||
const MIN_COLOR_VALUE = 127;
|
//
|
||||||
function newColor() {
|
// Created by Matti Lahtinen 4/3/2017
|
||||||
color = {
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
red: randomPastelRGBComponent(),
|
//
|
||||||
green: randomPastelRGBComponent(),
|
//
|
||||||
blue: randomPastelRGBComponent()
|
// Distributed under the Apache License, Version 2.0.
|
||||||
};
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
return color;
|
//
|
||||||
}
|
// Creates multiple "magnetic" blocks with random colors that users clones of and snap together.
|
||||||
// Helper functions.
|
|
||||||
function randomPastelRGBComponent() {
|
|
||||||
return Math.floor(Math.random() * MAX_RGB_COMPONENT_VALUE) + MIN_COLOR_VALUE;
|
(function() {
|
||||||
}
|
const MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum.
|
||||||
|
const MIN_COLOR_VALUE = 127;
|
||||||
|
const SIZE = 0.3;
|
||||||
|
const LIFETIME = 600;
|
||||||
|
|
||||||
|
// Random Pastel Generator based on Piper's script
|
||||||
|
function newColor() {
|
||||||
|
color = {
|
||||||
|
red: randomPastelRGBComponent(),
|
||||||
|
green: randomPastelRGBComponent(),
|
||||||
|
blue: randomPastelRGBComponent()
|
||||||
|
};
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
// Helper functions.
|
||||||
|
function randomPastelRGBComponent() {
|
||||||
|
return Math.floor(Math.random() * MAX_RGB_COMPONENT_VALUE) + MIN_COLOR_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
var SCRIPT_URL = Script.resolvePath("./entity_scripts/magneticBlock.js");
|
||||||
|
|
||||||
|
var frontVector = Quat.getFront(MyAvatar.orientation);
|
||||||
|
frontVector.y -=.25;
|
||||||
|
for(var x =0; x < 3; x++) {
|
||||||
|
for (var y = 0; y < 3; y++) {
|
||||||
|
|
||||||
|
var frontOffset = {
|
||||||
|
x: 0,
|
||||||
|
y: SIZE * y + SIZE,
|
||||||
|
z: SIZE * x + SIZE
|
||||||
|
};
|
||||||
|
|
||||||
|
Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
name: "MagneticBlock-" + y +'-' + x,
|
||||||
|
dimensions: {
|
||||||
|
x: SIZE,
|
||||||
|
y: SIZE,
|
||||||
|
z: SIZE
|
||||||
|
},
|
||||||
|
userData: JSON.stringify({grabbableKey: { cloneable: true, grabbable: true, cloneLifetime : LIFETIME, cloneLimit: 9999}}),
|
||||||
|
position: Vec3.sum(MyAvatar.position, Vec3.sum(frontOffset, frontVector)),
|
||||||
|
color: newColor(),
|
||||||
|
script: SCRIPT_URL
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.stop();
|
||||||
|
})();
|
||||||
|
|
Loading…
Reference in a new issue