mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 19:21:16 +02:00
Merge pull request #7267 from ericrius1/growingPlant
Plant that blooms flowers when it is watered by a water can
This commit is contained in:
commit
143d8a0929
5 changed files with 629 additions and 0 deletions
0
examples/VR-VJ/cartridgesSpawner.js
Normal file
0
examples/VR-VJ/cartridgesSpawner.js
Normal file
94
unpublishedScripts/DomainContent/Home/plant/flower.fs
Normal file
94
unpublishedScripts/DomainContent/Home/plant/flower.fs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
//
|
||||||
|
// flowers.fs
|
||||||
|
// examples/homeContent/plant
|
||||||
|
//
|
||||||
|
// Created by Eric Levin on 3/7/16.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This fragment shader is designed to shader a sphere to create the effect of a blooming flower
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
|
||||||
|
#define TWO_PI 6.28318530718
|
||||||
|
|
||||||
|
uniform float iBloomPct = 0.2;
|
||||||
|
uniform vec3 iHSLColor = vec3(0.7, 0.5, 0.5);
|
||||||
|
|
||||||
|
|
||||||
|
float hue2rgb(float f1, float f2, float hue) {
|
||||||
|
if (hue < 0.0)
|
||||||
|
hue += 1.0;
|
||||||
|
else if (hue > 1.0)
|
||||||
|
hue -= 1.0;
|
||||||
|
float res;
|
||||||
|
if ((6.0 * hue) < 1.0)
|
||||||
|
res = f1 + (f2 - f1) * 6.0 * hue;
|
||||||
|
else if ((2.0 * hue) < 1.0)
|
||||||
|
res = f2;
|
||||||
|
else if ((3.0 * hue) < 2.0)
|
||||||
|
res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
|
||||||
|
else
|
||||||
|
res = f1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 hsl2rgb(vec3 hsl) {
|
||||||
|
vec3 rgb;
|
||||||
|
|
||||||
|
if (hsl.y == 0.0) {
|
||||||
|
rgb = vec3(hsl.z); // Luminance
|
||||||
|
} else {
|
||||||
|
float f2;
|
||||||
|
|
||||||
|
if (hsl.z < 0.5)
|
||||||
|
f2 = hsl.z * (1.0 + hsl.y);
|
||||||
|
else
|
||||||
|
f2 = hsl.z + hsl.y - hsl.y * hsl.z;
|
||||||
|
|
||||||
|
float f1 = 2.0 * hsl.z - f2;
|
||||||
|
|
||||||
|
rgb.r = hue2rgb(f1, f2, hsl.x + (1.0/3.0));
|
||||||
|
rgb.g = hue2rgb(f1, f2, hsl.x);
|
||||||
|
rgb.b = hue2rgb(f1, f2, hsl.x - (1.0/3.0));
|
||||||
|
}
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 hsl2rgb(float h, float s, float l) {
|
||||||
|
return hsl2rgb(vec3(h, s, l));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
vec2 st = fragCoord.xy/iWorldScale.xz;
|
||||||
|
vec3 color = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
vec2 toCenter = vec2(0.5) - st;
|
||||||
|
float angle = atan(toCenter.y, toCenter.x);
|
||||||
|
float radius = length(toCenter) * 2.0;
|
||||||
|
|
||||||
|
// Second check is so we discard the top half of the sphere
|
||||||
|
if ( iBloomPct < radius || _position.y > 0) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
// simulate ambient occlusion
|
||||||
|
float brightness = pow(radius, 0.8);
|
||||||
|
vec3 hslColor = iHSLColor + (abs(angle) * 0.02);
|
||||||
|
hslColor.z = 0.15 + pow(radius, 2.);
|
||||||
|
vec3 rgbColor = hsl2rgb(hslColor);
|
||||||
|
fragColor = vec4(rgbColor, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vec4 getProceduralColor() {
|
||||||
|
vec4 result;
|
||||||
|
vec2 position = _position.xz;
|
||||||
|
position += 0.5;
|
||||||
|
|
||||||
|
mainImage(result, position * iWorldScale.xz);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
//
|
||||||
|
// growingPlantEntityScript.js
|
||||||
|
// examples/homeContent/plant
|
||||||
|
//
|
||||||
|
// Created by Eric Levin on 2/10/16.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This entity script handles the logic for growing a plant when it has water poured on it
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
Script.include('../../../../libraries/utils.js');
|
||||||
|
|
||||||
|
var _this;
|
||||||
|
GrowingPlant = function() {
|
||||||
|
_this = this;
|
||||||
|
_this.flowers = [];
|
||||||
|
// _this.STARTING_FLOWER_DIMENSIONS = {x: 0.1, y: 0.001, z: 0.1}
|
||||||
|
_this.STARTING_FLOWER_DIMENSIONS = {
|
||||||
|
x: 0.001,
|
||||||
|
y: 0.001,
|
||||||
|
z: 0.001
|
||||||
|
}
|
||||||
|
|
||||||
|
_this.MAX_FLOWERS = 50;
|
||||||
|
_this.MIN_FLOWER_TO_FLOWER_DISTANCE = 0.03;
|
||||||
|
|
||||||
|
_this.debounceRange = {
|
||||||
|
min: 500,
|
||||||
|
max: 1000
|
||||||
|
};
|
||||||
|
_this.canCreateFlower = true;
|
||||||
|
_this.SHADER_URL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/shaders/flower.fs";
|
||||||
|
// _this.SHADER_URL = "file:///C:/Users/Eric/hifi/unpublishedScripts/DomainContent/Home/plant/flower.fs";
|
||||||
|
|
||||||
|
_this.flowerHSLColors = [{
|
||||||
|
hue: 19 / 360,
|
||||||
|
saturation: 0.92,
|
||||||
|
light: 0.31
|
||||||
|
}, {
|
||||||
|
hue: 161 / 360,
|
||||||
|
saturation: 0.28,
|
||||||
|
light: 0.62
|
||||||
|
}];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GrowingPlant.prototype = {
|
||||||
|
|
||||||
|
|
||||||
|
continueWatering: function(entityID, data) {
|
||||||
|
// we're being watered- every now and then spawn a new flower to add to our growing list
|
||||||
|
// If we don't have any flowers yet, immediately grow one
|
||||||
|
var data = JSON.parse(data[0]);
|
||||||
|
|
||||||
|
if (_this.canCreateFlower && _this.flowers.length < _this.MAX_FLOWERS) {
|
||||||
|
_this.createFlower(data.position, data.surfaceNormal);
|
||||||
|
_this.canCreateFlower = false;
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
_this.canCreateFlower = true;
|
||||||
|
}, randFloat(_this.debounceRange.min, this.debounceRange.max));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_this.flowers.forEach(function(flower) {
|
||||||
|
flower.grow();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
createFlower: function(position, surfaceNormal) {
|
||||||
|
if (_this.previousFlowerPosition && Vec3.distance(position, _this.previousFlowerPosition) < _this.MIN_FLOWER_TO_FLOWER_DISTANCE) {
|
||||||
|
// Reduces flower overlap
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var xzGrowthRate = randFloat(0.00006, 0.00016);
|
||||||
|
var growthRate = {x: xzGrowthRate, y: randFloat(0.001, 0.003), z: xzGrowthRate};
|
||||||
|
|
||||||
|
var flower = {
|
||||||
|
dimensions: {
|
||||||
|
x: _this.STARTING_FLOWER_DIMENSIONS.x,
|
||||||
|
y: _this.STARTING_FLOWER_DIMENSIONS.y,
|
||||||
|
z: _this.STARTING_FLOWER_DIMENSIONS.z
|
||||||
|
},
|
||||||
|
startingPosition: position,
|
||||||
|
rotation: Quat.rotationBetween(Vec3.UNIT_Y, surfaceNormal),
|
||||||
|
maxYDimension: randFloat(0.4, 1.1),
|
||||||
|
// startingHSLColor: {
|
||||||
|
// hue: 80 / 360,
|
||||||
|
// saturation: 0.47,
|
||||||
|
// light: 0.48
|
||||||
|
// },
|
||||||
|
// endingHSLColor: {
|
||||||
|
// hue: 19 / 260,
|
||||||
|
// saturation: 0.92,
|
||||||
|
// light: 0.41
|
||||||
|
// },
|
||||||
|
hslColor: Math.random() < 0.5 ? _this.flowerHSLColors[0] : _this.flowerHSLColors[1],
|
||||||
|
growthRate: growthRate
|
||||||
|
};
|
||||||
|
flower.userData = {
|
||||||
|
ProceduralEntity: {
|
||||||
|
shaderUrl: _this.SHADER_URL,
|
||||||
|
uniforms: {
|
||||||
|
iBloomPct: randFloat(0.4, 0.8),
|
||||||
|
iHSLColor: [flower.hslColor.hue, flower.hslColor.saturation, flower.hslColor.light]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
flower.id = Entities.addEntity({
|
||||||
|
type: "Sphere",
|
||||||
|
name: "flower",
|
||||||
|
lifetime: 3600,
|
||||||
|
position: position,
|
||||||
|
collisionless: true,
|
||||||
|
rotation: flower.rotation,
|
||||||
|
dimensions: _this.STARTING_FLOWER_DIMENSIONS,
|
||||||
|
userData: JSON.stringify(flower.userData)
|
||||||
|
});
|
||||||
|
flower.grow = function() {
|
||||||
|
// grow flower a bit
|
||||||
|
if (flower.dimensions.y > flower.maxYDimension) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flower.dimensions = Vec3.sum(flower.dimensions, flower.growthRate);
|
||||||
|
flower.position = Vec3.sum(flower.startingPosition, Vec3.multiply(Quat.getUp(flower.rotation), flower.dimensions.y / 2));
|
||||||
|
//As we grow we must also move ourselves in direction we grow!
|
||||||
|
//TODO: Add this color changing back once we fix bug https://app.asana.com/0/inbox/31759584831096/96943843100173/98022172055918
|
||||||
|
// var newHue = map(flower.dimensions.y, _this.STARTING_FLOWER_DIMENSIONS.y, flower.maxYDimension, flower.startingHSLColor.hue, flower.endingHSLColor.hue);
|
||||||
|
// var newSaturation = map(flower.dimensions.y, _this.STARTING_FLOWER_DIMENSIONS.y, flower.maxYDimension, flower.startingHSLColor.saturation, flower.endingHSLColor.saturation);
|
||||||
|
// var newLight = map(flower.dimensions.y, _this.STARTING_FLOWER_DIMENSIONS.y, flower.maxYDimension, flower.startingHSLColor.light, flower.endingHSLColor.light);
|
||||||
|
// flower.userData.PrsoceduralEntity.uniforms.iHSLColor = [newHue, newSaturation, newLight];
|
||||||
|
Entities.editEntity(flower.id, {
|
||||||
|
dimensions: flower.dimensions,
|
||||||
|
position: flower.position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_this.flowers.push(flower);
|
||||||
|
_this.previousFlowerPosition = position;
|
||||||
|
},
|
||||||
|
|
||||||
|
preload: function(entityID) {
|
||||||
|
_this.entityID = entityID;
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// entity scripts always need to return a newly constructed object of our type
|
||||||
|
return new GrowingPlant();
|
||||||
|
});
|
|
@ -0,0 +1,139 @@
|
||||||
|
//
|
||||||
|
// growingPlantSpawner.js
|
||||||
|
// examples/homeContent/plant
|
||||||
|
//
|
||||||
|
// Created by Eric Levin on 2/10/16.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This entity script handles the logic for growing a plant when it has water poured on it
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
|
||||||
|
var orientation = Camera.getOrientation();
|
||||||
|
orientation = Quat.safeEulerAngles(orientation);
|
||||||
|
orientation.x = 0;
|
||||||
|
orientation = Quat.fromVec3Degrees(orientation);
|
||||||
|
|
||||||
|
|
||||||
|
var bowlPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(orientation)));
|
||||||
|
var BOWL_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Flowers--Bowl.fbx";
|
||||||
|
var bowlDimensions = {
|
||||||
|
x: 0.518,
|
||||||
|
y: 0.1938,
|
||||||
|
z: 0.5518
|
||||||
|
};
|
||||||
|
var bowl = Entities.addEntity({
|
||||||
|
type: "Model",
|
||||||
|
modelURL: BOWL_MODEL_URL,
|
||||||
|
dimensions: bowlDimensions,
|
||||||
|
name: "plant bowl",
|
||||||
|
position: bowlPosition
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var PLANT_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Flowers--Moss-Rock.fbx";
|
||||||
|
var PLANT_SCRIPT_URL = Script.resolvePath("growingPlantEntityScript.js?v1" + Math.random().toFixed(2));
|
||||||
|
var plantDimensions = {
|
||||||
|
x: 0.52,
|
||||||
|
y: 0.2600,
|
||||||
|
z: 0.52
|
||||||
|
};
|
||||||
|
var plantPosition = Vec3.sum(bowlPosition, {
|
||||||
|
x: 0,
|
||||||
|
y: plantDimensions.y / 2,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
|
var plant = Entities.addEntity({
|
||||||
|
type: "Model",
|
||||||
|
modelURL: PLANT_MODEL_URL,
|
||||||
|
name: "hifi-growable-plant",
|
||||||
|
dimensions: plantDimensions,
|
||||||
|
position: plantPosition,
|
||||||
|
script: PLANT_SCRIPT_URL,
|
||||||
|
parentID: bowl
|
||||||
|
});
|
||||||
|
|
||||||
|
var WATER_CAN_MODEL_URL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/waterCan.fbx?v1" + Math.random();
|
||||||
|
var WATER_CAN_SCRIPT_URL = Script.resolvePath("waterCanEntityScript.js?v2" + Math.random().toFixed());
|
||||||
|
var waterCanPosition = Vec3.sum(plantPosition, Vec3.multiply(0.6, Quat.getRight(orientation)));
|
||||||
|
var waterCanRotation = orientation;
|
||||||
|
var waterCan = Entities.addEntity({
|
||||||
|
type: "Model",
|
||||||
|
shapeType: 'box',
|
||||||
|
name: "hifi-water-can",
|
||||||
|
modelURL: WATER_CAN_MODEL_URL,
|
||||||
|
script: WATER_CAN_SCRIPT_URL,
|
||||||
|
dimensions: {
|
||||||
|
x: 0.1859,
|
||||||
|
y: 0.2762,
|
||||||
|
z: 0.4115
|
||||||
|
},
|
||||||
|
position: waterCanPosition,
|
||||||
|
angularDamping: 1,
|
||||||
|
dynamic: true,
|
||||||
|
gravity: {
|
||||||
|
x: 0.0,
|
||||||
|
y: -2.0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
rotation: waterCanRotation,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
wearable: {
|
||||||
|
joints: {
|
||||||
|
RightHand: [{
|
||||||
|
x: 0.024,
|
||||||
|
y: 0.173,
|
||||||
|
z: 0.152
|
||||||
|
}, {
|
||||||
|
x: 0.374,
|
||||||
|
y: 0.636,
|
||||||
|
z: -0.638,
|
||||||
|
w: -0.215
|
||||||
|
}],
|
||||||
|
LeftHand: [{
|
||||||
|
x: -0.0348,
|
||||||
|
y: 0.201,
|
||||||
|
z: 0.166
|
||||||
|
}, {
|
||||||
|
x: 0.4095,
|
||||||
|
y: -0.625,
|
||||||
|
z: 0.616,
|
||||||
|
w: -0.247
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var waterSpoutPosition = Vec3.sum(waterCanPosition, Vec3.multiply(0.2, Quat.getFront(orientation)))
|
||||||
|
var waterSpoutRotation = Quat.multiply(waterCanRotation, Quat.fromPitchYawRollDegrees(10, 0, 0));
|
||||||
|
var waterSpout = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
name: "hifi-water-spout",
|
||||||
|
dimensions: {
|
||||||
|
x: 0.02,
|
||||||
|
y: 0.02,
|
||||||
|
z: 0.07
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 200,
|
||||||
|
green: 10,
|
||||||
|
blue: 200
|
||||||
|
},
|
||||||
|
position: waterSpoutPosition,
|
||||||
|
rotation: waterSpoutRotation,
|
||||||
|
parentID: waterCan,
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
// Entities.deleteEntity(plant);
|
||||||
|
// Entities.deleteEntity(bowl);
|
||||||
|
// Entities.deleteEntity(waterCan);
|
||||||
|
// Entities.deleteEntity(waterSpout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
|
@ -0,0 +1,242 @@
|
||||||
|
//
|
||||||
|
// waterCanEntityScript.js
|
||||||
|
// examples/homeContent/plant
|
||||||
|
//
|
||||||
|
// Created by Eric Levin on 2/15/16.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This entity script handles the logic for pouring water when a user tilts the entity the script is attached too.
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
Script.include('../../../../libraries/utils.js');
|
||||||
|
|
||||||
|
var _this;
|
||||||
|
WaterSpout = function() {
|
||||||
|
_this = this;
|
||||||
|
_this.waterSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/shower.wav");
|
||||||
|
_this.POUR_ANGLE_THRESHOLD = 0;
|
||||||
|
_this.waterPouring = false;
|
||||||
|
_this.WATER_SPOUT_NAME = "hifi-water-spout";
|
||||||
|
_this.GROWABLE_ENTITIES_SEARCH_RANGE = 100;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
WaterSpout.prototype = {
|
||||||
|
|
||||||
|
startNearGrab: function() {
|
||||||
|
_this.startHold();
|
||||||
|
},
|
||||||
|
|
||||||
|
startEquip: function() {
|
||||||
|
_this.startHold();
|
||||||
|
},
|
||||||
|
|
||||||
|
startHold: function() {
|
||||||
|
_this.findGrowableEntities();
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseEquip: function() {
|
||||||
|
_this.releaseHold();
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseGrab: function() {
|
||||||
|
_this.releaseHold();
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseHold: function() {
|
||||||
|
_this.stopPouring();
|
||||||
|
},
|
||||||
|
|
||||||
|
stopPouring: function() {
|
||||||
|
Entities.editEntity(_this.waterEffect, {
|
||||||
|
isEmitting: false
|
||||||
|
});
|
||||||
|
_this.waterPouring = false;
|
||||||
|
//water no longer pouring...
|
||||||
|
if (_this.waterInjector) {
|
||||||
|
_this.waterInjector.stop();
|
||||||
|
}
|
||||||
|
Entities.callEntityMethod(_this.mostRecentIntersectedGrowableEntity, 'stopWatering');
|
||||||
|
},
|
||||||
|
continueEquip: function() {
|
||||||
|
_this.continueHolding();
|
||||||
|
},
|
||||||
|
|
||||||
|
continueNearGrab: function() {
|
||||||
|
_this.continueHolding();
|
||||||
|
},
|
||||||
|
|
||||||
|
continueHolding: function() {
|
||||||
|
if (!_this.waterSpout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check rotation of water can along it's z axis. If it's beyond a threshold, then start spraying water
|
||||||
|
_this.castRay();
|
||||||
|
var rotation = Entities.getEntityProperties(_this.entityID, "rotation").rotation;
|
||||||
|
var pitch = Quat.safeEulerAngles(rotation).x;
|
||||||
|
if (pitch < _this.POUR_ANGLE_THRESHOLD) {
|
||||||
|
// Water is pouring
|
||||||
|
var spoutProps = Entities.getEntityProperties(_this.waterSpout, ["rotation", "position"]);
|
||||||
|
if (!_this.waterPouring) {
|
||||||
|
Entities.editEntity(_this.waterEffect, {
|
||||||
|
isEmitting: true
|
||||||
|
});
|
||||||
|
_this.waterPouring = true;
|
||||||
|
if (!_this.waterInjector) {
|
||||||
|
_this.waterInjector = Audio.playSound(_this.waterSound, {
|
||||||
|
position: spoutProps.position,
|
||||||
|
loop: true
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_this.waterInjector.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_this.waterSpoutRotation = spoutProps.rotation;
|
||||||
|
var waterEmitOrientation = Quat.multiply(_this.waterSpoutRotation, Quat.fromPitchYawRollDegrees(0, 180, 0));
|
||||||
|
Entities.editEntity(_this.waterEffect, {
|
||||||
|
emitOrientation: waterEmitOrientation
|
||||||
|
});
|
||||||
|
} else if (pitch > _this.POUR_ANGLE_THRESHOLD && _this.waterPouring) {
|
||||||
|
_this.stopPouring();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
castRay: function() {
|
||||||
|
var spoutProps = Entities.getEntityProperties(_this.waterSpout, ["position, rotation"]);
|
||||||
|
var direction = Quat.getFront(spoutProps.rotation)
|
||||||
|
var end = Vec3.sum(spoutProps.position, Vec3.multiply(5, direction));
|
||||||
|
|
||||||
|
var pickRay = {
|
||||||
|
origin: spoutProps.position,
|
||||||
|
direction: direction
|
||||||
|
};
|
||||||
|
var intersection = Entities.findRayIntersection(pickRay, true, _this.growableEntities);
|
||||||
|
|
||||||
|
if (intersection.intersects) {
|
||||||
|
//We've intersected with a waterable object
|
||||||
|
var data = JSON.stringify({
|
||||||
|
position: intersection.intersection,
|
||||||
|
surfaceNormal: intersection.surfaceNormal
|
||||||
|
});
|
||||||
|
_this.mostRecentIntersectedGrowableEntity = intersection.entityID;
|
||||||
|
Entities.callEntityMethod(intersection.entityID, 'continueWatering', [data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
createWaterEffect: function() {
|
||||||
|
var waterEffectPosition = Vec3.sum(_this.waterSpoutPosition, Vec3.multiply(Quat.getFront(_this.waterSpoutRotation), -0.04));
|
||||||
|
_this.waterEffect = Entities.addEntity({
|
||||||
|
type: "ParticleEffect",
|
||||||
|
name: "water particle effect",
|
||||||
|
position: waterEffectPosition,
|
||||||
|
isEmitting: false,
|
||||||
|
parentID: _this.waterSpout,
|
||||||
|
colorStart: {
|
||||||
|
red: 90,
|
||||||
|
green: 90,
|
||||||
|
blue: 110
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 70,
|
||||||
|
green: 70,
|
||||||
|
blue: 130
|
||||||
|
},
|
||||||
|
colorFinish: {
|
||||||
|
red: 23,
|
||||||
|
green: 195,
|
||||||
|
blue: 206
|
||||||
|
},
|
||||||
|
maxParticles: 20000,
|
||||||
|
lifespan: 2,
|
||||||
|
emitRate: 2000,
|
||||||
|
emitSpeed: .3,
|
||||||
|
speedSpread: 0.1,
|
||||||
|
emitDimensions: {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.0
|
||||||
|
},
|
||||||
|
emitAcceleration: {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
polarStart: 0.0,
|
||||||
|
polarFinish: 0.1,
|
||||||
|
accelerationSpread: {
|
||||||
|
x: 0.01,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.01
|
||||||
|
},
|
||||||
|
emitOrientation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
||||||
|
radiusSpread: 0.0001,
|
||||||
|
radiusStart: 0.005,
|
||||||
|
particleRadius: 0.003,
|
||||||
|
radiusFinish: 0.001,
|
||||||
|
alphaSpread: 0,
|
||||||
|
alphaStart: 0.1,
|
||||||
|
alpha: 1.0,
|
||||||
|
alphaFinish: 1.0,
|
||||||
|
emitterShouldTrail: true,
|
||||||
|
textures: "https://s3-us-west-1.amazonaws.com/hifi-content/eric/images/raindrop.png",
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
findGrowableEntities: function() {
|
||||||
|
_this.growableEntities = [];
|
||||||
|
var entities = Entities.findEntities(_this.position, _this.GROWABLE_ENTITIES_SEARCH_RANGE);
|
||||||
|
entities.forEach(function(entity) {
|
||||||
|
var name = Entities.getEntityProperties(entity, "name").name;
|
||||||
|
if (name.length > 0 && name.indexOf("growable") !== -1) {
|
||||||
|
_this.growableEntities.push(entity);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
preload: function(entityID) {
|
||||||
|
_this.entityID = entityID;
|
||||||
|
_this.position = Entities.getEntityProperties(_this.entityID, "position").position;
|
||||||
|
// Wait a a bit for spout to spawn for case where preload is initial spawn, then save it
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
var entities = Entities.findEntities(_this.position, 1);
|
||||||
|
entities.forEach(function(entity) {
|
||||||
|
var name = Entities.getEntityProperties(entity, "name").name;
|
||||||
|
if (name === _this.WATER_SPOUT_NAME) {
|
||||||
|
_this.waterSpout = entity;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_this.waterSpout) {
|
||||||
|
_this.waterSpoutPosition = Entities.getEntityProperties(_this.waterSpout, "position").position;
|
||||||
|
_this.waterSpoutRotation = Entities.getEntityProperties(_this.waterSpout, "rotation").rotation;
|
||||||
|
_this.createWaterEffect();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
unload: function() {
|
||||||
|
Entities.deleteEntity(_this.waterEffect);
|
||||||
|
if (_this.waterInjector) {
|
||||||
|
_this.waterInjector.stop();
|
||||||
|
delete _this.waterInjector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// entity scripts always need to return a newly constructed object of our type
|
||||||
|
return new WaterSpout();
|
||||||
|
});
|
Loading…
Reference in a new issue